工程師如何對待開源

工程師如何對待開源

本文是筆者作為一個在知名科技企業(yè)內(nèi)從事開源相關(guān)工作超過?20?年的工程師,親身經(jīng)歷或者親眼目睹很多工程師對待開源軟件的優(yōu)秀實踐,也看到了很多?Bad Cases,所以想把自己的一些心得體會寫在這里,供工程師進(jìn)行參考,希望能幫助工程師更好的成長。

概述

作為一個在科技企業(yè)內(nèi)部進(jìn)行技術(shù)工作的工程師,工作任務(wù)就是用技術(shù)手段支持和實現(xiàn)公司所關(guān)注的商業(yè)目標(biāo)。?實際工作過程中,需要主動或者被動的使用和維護(hù)大量的開源軟件。?據(jù)統(tǒng)計,每個工程師在企業(yè)內(nèi)部進(jìn)行研發(fā)和運維等工作的時候,每年會接觸到上千款開源軟件,?如果是以?Java?或?JavaSciprt?為主要程序開發(fā)語言的工程師,則接觸到的開源軟件數(shù)量更多,在萬級別甚至十萬級別。?(數(shù)據(jù)來源:《2020 State of the Software Supply Chain》由?Sonatype?發(fā)布)

那么如何選擇開源軟件??這么多開源軟件中,如何根據(jù)個人需求和業(yè)務(wù)需要來選擇合適的開源項目來進(jìn)行投入,是需要綜合考慮的。

選擇了開源軟件之后又如何進(jìn)行定制和長期維護(hù)??這也是一個很大的問題。因為在企業(yè)內(nèi)部開發(fā)軟件,跟個人開發(fā)軟件不一樣的是,維護(hù)一個計算機軟件系統(tǒng)的成本遠(yuǎn)遠(yuǎn)大于開發(fā)該系統(tǒng)或軟件的成本。選擇開源軟件之后,如何從長期的視角進(jìn)行定制和修改,后續(xù)的長期維護(hù)如何進(jìn)行,才能做到高效和節(jié)省成本,業(yè)內(nèi)有很多很好的經(jīng)驗,也有不少不太成功的案例成為教訓(xùn)。

最后回到個人,工程師的成長是在不斷的學(xué)習(xí)和實踐中進(jìn)行的。如何來利用開源來提升自己能力,擴(kuò)大自己的眼界,提高自己技術(shù)口碑和業(yè)內(nèi)影響力,對于工程師本人也是非常重要的。

本文將從如下三個部分來分別闡述:

工程師如何選擇開源軟件

工程師如何定制和維護(hù)開源軟件

工程師個人成長如何利用開源

1.?如何選擇開源軟件

首先要明確對開源軟件的態(tài)度,在現(xiàn)階段是不可能離開對開源軟件的使用的。?使用開源軟件有各種各樣的風(fēng)險,包括開源合規(guī)、安全、效率的問題。?簡化為一句:在企業(yè)內(nèi)部使用開源軟件,需要遵守該企業(yè)對開源軟件的內(nèi)部規(guī)定,包括如何引入和如何維護(hù),以便達(dá)到高效、安全、合規(guī)的使用。

回到具體如何選擇特定的開源軟件的問題上,有如下幾個緯度可以進(jìn)行參考。

根據(jù)需求

根據(jù)技術(shù)發(fā)展趨勢

根據(jù)軟件采納周期的不同階段

根據(jù)開源軟件的成熟度情況

根據(jù)項目的質(zhì)量指標(biāo)

根據(jù)項目的治理模式

1.1?根據(jù)需求來選擇開源軟件

選擇開源軟件,首先要明確需求,即選擇這個開源軟件的目的究竟是什么。?工程師選擇一個開源軟件,究竟是它用來做什么的,是用來進(jìn)行個人學(xué)習(xí)的;?還是用來滿足?ToB?客戶的需求的;還是用來滿足內(nèi)部服務(wù)開發(fā)的需求的。?這三個不同的目的下,選擇開源軟件的導(dǎo)向完全不一樣。?(注意:后兩個場景是需要先考慮企業(yè)開源合規(guī)的需求的,參見第三章)

先說說選擇開源軟件來進(jìn)行個人學(xué)習(xí),那么需要看看個人學(xué)習(xí)的具體目的究竟是什么。?是想學(xué)習(xí)一種比較流行的技術(shù)來完善個人的技術(shù)知識結(jié)構(gòu)擴(kuò)大個人技術(shù)視野;還是想看看相應(yīng)的開源技術(shù)項目的具體實現(xiàn),來作為內(nèi)部項目技術(shù)開發(fā)的參考;還是想為了下一份工作進(jìn)行有針對性的技術(shù)準(zhǔn)備。不同的目的會導(dǎo)致不同的選擇。針對前者,顯然是什么技術(shù)最流行選什么,自己缺什么選什么;針對第二種目的,一般是對該技術(shù)領(lǐng)域的知名開源軟件或者創(chuàng)新性軟件進(jìn)行有針對性的選擇,即某個特性是我當(dāng)前需要的,或者是我當(dāng)前項目實現(xiàn)不好的,我需要看看別人是如何實現(xiàn)的。最后一種,顯然是按照下一份工作的職位需要和技術(shù)棧要求進(jìn)行準(zhǔn)備,并根據(jù)技術(shù)棧要求的門檻高低進(jìn)行選擇。但是注意,從個人需求出發(fā)選擇開源軟件,一般都需要寫個小項目練練手,比如一個?Demo?程序或者一個測試服務(wù),因為不用考慮后續(xù)的長期維護(hù),所以盡可以按照個人的想法和個人研發(fā)習(xí)慣進(jìn)行各種練習(xí),不用遵循企業(yè)內(nèi)部的開發(fā)流程和質(zhì)量要求,也不用考慮該開源軟件的穩(wěn)定性和社區(qū)成熟度等情況,只需要盡情的學(xué)習(xí)和參考代碼就好了。

然后看下一個需求,選擇開源軟件進(jìn)行研發(fā)的軟件是需要提供給客戶的,往往可能還是以私有云的方式進(jìn)行交付?;诖祟愋枨髞磉x擇開源軟件,注意作好平衡,即客戶的需求和企業(yè)自身技術(shù)規(guī)劃或產(chǎn)品的長期規(guī)劃需要。以私有云方式進(jìn)入客戶的?IDC?環(huán)境,是需要跟客戶開發(fā)和運行環(huán)境的上下游項目進(jìn)行集成的。這時候要看客戶的需要,可能某些客戶對開源軟件有特定的要求,例如要求使用?HDFS?而且是某個特定版本。對這類指定軟件名字和指定版本的要求,有可能是因為客戶當(dāng)前比較熟悉這個版本,也有可能是因為之前其他軟硬件供應(yīng)商提供的軟件和版本,指定的目的是方便集成和后續(xù)的使用與維護(hù)。如果這種需求是符合企業(yè)項目或者產(chǎn)品的長期發(fā)展需求的,則是可以完全滿足的。如果甲方非常強勢,除了滿足他的要求之外沒有別的辦法,那就選擇客戶所指定的軟件和版本好了。但是如果跟自身項目或產(chǎn)品的長期發(fā)展需求不一致,而且具體項目或者版本是可以跟甲方進(jìn)行協(xié)商的,那么需要跟客戶協(xié)商出一個雙方都能接受的結(jié)果出來,即選擇特定的開源軟件和版本既要做到客戶滿意并買單,又要做到自身的交付成本可控,還要做到符合自身項目或者產(chǎn)品的長期發(fā)展需要。例如客戶使用?Java?的某個老版本,但是企業(yè)的?toB?交付的軟件要求使用?Java?的較高版本。那么需要跟客戶協(xié)商,要么切換到企業(yè)希望的版本上,還需要幫助客戶完成已有系統(tǒng)的升級工作;要么只能降低自身軟件的?Java?版本需求,可能還需要對某些自身代碼進(jìn)行修改,還可能對軟件中的某些依賴組件進(jìn)行修改。這個場景下是帶有很多客觀約束條件下的選擇,是需要跟客戶,自身的產(chǎn)品經(jīng)理和架構(gòu)師一起協(xié)商的。

最后,如果場景是為了滿足內(nèi)部服務(wù)的需求,即選擇開源軟件來搭建的服務(wù)是給內(nèi)部業(yè)務(wù)或者最終用戶來使用的,常見于國內(nèi)各大互聯(lián)網(wǎng)公司的互聯(lián)網(wǎng)服務(wù)系統(tǒng)和各種手機上的?App。這時候項目的開發(fā)和維護(hù)方有較大的自主權(quán),跟?toB?的交付業(yè)務(wù)完全不一樣。此時選擇開源軟件,就一定要綜合考慮開發(fā)和維護(hù)成本,還要考慮使用該服務(wù)的業(yè)務(wù)所處的階段。

(1)如果提供的服務(wù)是給創(chuàng)新業(yè)務(wù)使用的,創(chuàng)新業(yè)務(wù)一般都是試錯業(yè)務(wù),隨時需要根據(jù)市場情況的變化和當(dāng)前執(zhí)行的狀態(tài)進(jìn)行調(diào)整,很可能三個月后這個項目沒了,即被取消了。這種情況下?“糙快猛”?的開發(fā)方式是比較合適的,不用太多考慮系統(tǒng)的可維護(hù)性和可擴(kuò)展性,就用研發(fā)團(tuán)隊最熟悉的軟件技術(shù)棧,然后用底層技術(shù)支撐團(tuán)隊比如基礎(chǔ)架構(gòu)團(tuán)隊提供的成熟而且經(jīng)過驗證后的底層基礎(chǔ)技術(shù)平臺就可以,最重要是盡快把系統(tǒng)搭建出來,然后隨著產(chǎn)品進(jìn)行快速的迭代。這個時候需要盡量降低現(xiàn)有研發(fā)運維團(tuán)隊的學(xué)習(xí)成本和開發(fā)成本,不用太多考慮可維護(hù)成本,因為需要糙快猛的把系統(tǒng)堆出來,驗證產(chǎn)品需求和商業(yè)模式是最重要的,時間最重要。如果發(fā)現(xiàn)有市場機會,就快速跟進(jìn),站穩(wěn)腳跟之后可以采用省時間但是費資源的方式(俗稱?“堆機器”)來進(jìn)行擴(kuò)展,或者采用?“邊開飛機邊換引擎”?的模式進(jìn)行重寫都是比較劃算的。對于處于創(chuàng)業(yè)階段的企業(yè)或者項目來說,速度勝過一切。

(2)但是如果選擇開源軟件搭建出來的計算機軟件系統(tǒng)或者服務(wù),是需要長期維護(hù)的,比如是給公司內(nèi)成熟業(yè)務(wù)使用的,或者是針對公司內(nèi)成熟平臺的缺點進(jìn)行系統(tǒng)升級并要替代原有產(chǎn)品的,那么在滿足業(yè)務(wù)需求的前提下,考慮系統(tǒng)的可維護(hù)性變成最重要的事情。選擇對應(yīng)的開源軟件,它是否成熟,是否穩(wěn)定;二次開發(fā)是否友好;運維成本是否比較合算即比較省機器和帶寬;運維操作是否方便,例如常見的擴(kuò)容和縮容操作是否可以高效、自動、無損的完成;Upstream?到上游開源社區(qū)是否容易等等,這些都成為需要重點考慮的事情。這種情況下,開發(fā)一個系統(tǒng)的成本,可能只占整個系統(tǒng)生命周期內(nèi)的成本的?1/10?不到。所以在滿足需求的前提下,重點考慮可維護(hù)性。

1.2?根據(jù)技術(shù)發(fā)展趨勢來選擇開源軟件

如上圖所示,現(xiàn)代計算機軟件或者服務(wù)的研發(fā),是一個不斷運行的循環(huán)和迭代過程。從市場分析開始,然后進(jìn)入到創(chuàng)意階段,再到編碼階段,最后到上線階段完成應(yīng)用的部署和生效,上線之后根據(jù)得到的數(shù)據(jù)反饋,繼續(xù)進(jìn)行分析。這個循環(huán)迭代的過程,顯然對于一個身處競爭激烈的行業(yè)的企業(yè)來說,迭代的速度越快越好,同時也需要具備快速彈性、低成本伸縮的能力,即產(chǎn)品方向?qū)α?,那么趕緊進(jìn)行系統(tǒng)擴(kuò)容,承接快速增長的流量,做到快速增長;如果產(chǎn)品方向不對,需要趕緊縮容,把相關(guān)硬件和人力資源節(jié)省出來,投入到新的試錯方向上去。身處同一個行業(yè)內(nèi)的企業(yè),如果企業(yè)?A?能以更低的成本,更快的速度的進(jìn)行各種產(chǎn)品和策略的迭代,顯然它是能比迭代速度慢,成本高的企業(yè)?B?是有更好的競爭優(yōu)勢的。

現(xiàn)在的開源軟件數(shù)量非常多,幾乎每一個分類下面都有很多的開源項目。針對某一個具體的需求,如何進(jìn)行選擇?一個建議是根據(jù)技術(shù)趨勢進(jìn)行選擇。即現(xiàn)在的計算機系統(tǒng)迭代的方式是?Agile(敏捷)?+ Scale(擴(kuò)展)。顯然,能夠支持計算機系統(tǒng)進(jìn)行快速迭代,并能夠很方便進(jìn)行低成本彈性伸縮的開源軟件是值得進(jìn)行長期投入的。而對一個新的開源軟件的學(xué)習(xí)和使用,學(xué)習(xí)者是希望該軟件的學(xué)習(xí)門檻越低越好。一個流行的開源軟件,內(nèi)部實現(xiàn)可以盡可能的復(fù)雜,但是對于用戶來說一定是需要用戶友好的。不然即使創(chuàng)新度再好,易用性不好,只有極客才能學(xué)習(xí)和掌握,創(chuàng)新的鴻溝是很難跨越的。

例如?Docker?的出現(xiàn)之后,以極快的速度風(fēng)靡全球,非常多的工程師喜歡上了?Docker。就是因為?Docker?的特性,在傳統(tǒng)的容器系統(tǒng)之上增加了新特性,包括把應(yīng)用程序和底層依賴庫封裝為一個容器鏡像,容器鏡像有版本,而且可以通過集中的鏡像倉庫進(jìn)行存儲和大批量分發(fā)。Docker?首先解決了長期困擾工程師的開發(fā)、測試、上線環(huán)境標(biāo)準(zhǔn)化的問題,能夠支持開發(fā)者進(jìn)行快速的迭代。同時使用了統(tǒng)一的鏡像倉庫來進(jìn)行鏡像的分發(fā),而且底層采用了輕量級虛擬機即容器的技術(shù),可以非??斓谋焕穑圆捎?Docker?的系統(tǒng)可以很方便的進(jìn)行彈性擴(kuò)展。同時,因為把應(yīng)用?App?封裝在一個鏡像里面,可以在邏輯上根據(jù)?Domain Model?的設(shè)計原則進(jìn)行更好的抽象和復(fù)用。顯然,這樣的技術(shù)是值得每一個開發(fā)計算機系統(tǒng)的工程師學(xué)習(xí)和掌握的。因為他能帶來極大的方便。相反,在?Docker?產(chǎn)生之前,雖然?Control Group(簡稱?cgroup)?+ Namespace?的技術(shù)早就已經(jīng)出現(xiàn),并早就集成在?Linux?內(nèi)核中,Google?的?borg?相關(guān)的論文早就已經(jīng)發(fā)表,但是一般的技術(shù)研發(fā)團(tuán)隊不是很容易就能駕馭容器并把容器系統(tǒng)在公司內(nèi)部大規(guī)模進(jìn)行部署的。印象中?borg?論文出現(xiàn)后,國內(nèi)只有?BAT?級別的互聯(lián)網(wǎng)公司,才有一小撮精英研發(fā)團(tuán)隊來研發(fā)和使用容器管理系統(tǒng),例如百度負(fù)責(zé)?Matrix?系統(tǒng)研發(fā)的團(tuán)隊,阿里負(fù)責(zé)?Pounch?系統(tǒng)研發(fā)的團(tuán)隊,騰訊也有一個小團(tuán)隊負(fù)責(zé)容器系統(tǒng)的研究。但是除了那一小部分團(tuán)隊,更多的工程師因為相對較難的學(xué)習(xí)難度而沒有把容器大批的用起來。而?Docker?這種技術(shù),就是非常好的順應(yīng)了敏捷和彈性擴(kuò)展的技術(shù)趨勢,而且提供了非常好的用戶易用性,然后一出場就被非常多的工程師迅速使用上了,而且成為市場的默認(rèn)標(biāo)準(zhǔn)。

這些順應(yīng)潮流的開源軟件是值得選擇和投入的。

另外一個例子是?Spark,Spark?的出現(xiàn)解決了?MapReduce?在分布式計算過程中因為需要頻繁進(jìn)行?IO?操作導(dǎo)致的性能比較低下的問題,同時在易用性上有較大的提升,所以才取代了?MapReduce?在分布式計算領(lǐng)域內(nèi)的主流地位。

1.3?根據(jù)開源軟件采納周期的不同階段進(jìn)行選擇

軟件作為智力活動的產(chǎn)物,他有他的生命周期,一般用軟件的技術(shù)采納曲線表示。

開源軟件也是軟件的一種,也都是遵循軟件的技術(shù)采納規(guī)律的。如下圖所示:

一個開源軟件從創(chuàng)建到衰亡一般會經(jīng)過?5?個階段。?從創(chuàng)新期(Innovators,占比?2.5%),到早期采納期(Early Adopters,占比?13.5%),然后跨越鴻溝(chasm),進(jìn)入到早期大眾期(Early Majority,占比?34%),再進(jìn)入后期大眾期(Late Majority,占比?34%),最后進(jìn)入衰退期(Laggards,占比?16%)。絕大部分的開源創(chuàng)新項目,沒有能成功的跨域鴻溝,即從早期采納階段進(jìn)入到早期大眾階段,就消亡掉了。?所以,如果是選擇一個需要長期使用并維護(hù)的開源項目,選擇處于早期大眾或者后期大眾狀態(tài)的項目是比較理智和科學(xué)的。

當(dāng)然如果只是個人想學(xué)習(xí)一個新的東西,可以看看處于創(chuàng)新者狀態(tài)的開源項目,或者看看處于?“早期采納者”?狀態(tài)的項目。

注意不管是從長期研發(fā)系統(tǒng)的角度,還是從個人學(xué)習(xí)的角度,都不要再去看處于衰退期(Laggards)的項目了。?例如現(xiàn)階段即?2022?年,是不用再去選擇?Mesos,Docker Swarm?之類的項目了。自從?Kubernetes?成為容器調(diào)度技術(shù)分類的默認(rèn)標(biāo)準(zhǔn),這兩個項目就已經(jīng)處于衰退期,他們的母公司都已經(jīng)放棄了。這個階段如果還投入較多精力來開發(fā)和維護(hù),除非真的是非常強勢的甲方要求,把錢砸在工程師面前逼的不得不用才會選擇。

同學(xué)們可能會問,從哪里可以看到這些技術(shù)采納度曲線?

InfoQ,gartner,thoughtworks?每年都會更新他們各自的技術(shù)采納度曲線并公布出來,?大家可以在網(wǎng)上搜索一下,看看他們各自的技術(shù)采納圖是什么,然后結(jié)合一些業(yè)內(nèi)的經(jīng)驗,得出自己的判斷。

例如https://con.infoq.cn/conference/technology-selection?tab=bigdata

從這里能看到?2022?年?InfoQ?對?BigData?領(lǐng)域各種流行技術(shù)的判斷。?

從上圖可以看出,Hudi、Clickhouse、Delta Lake?等開源軟件還處于創(chuàng)新者的階段,即在工業(yè)界采納還比較少,對于想學(xué)習(xí)新項目的同學(xué)是可以重點關(guān)注的。但是現(xiàn)在這些開源軟件還不適合應(yīng)用在需要長期維護(hù)的成熟應(yīng)用場景里面。

注意這些知名科技媒體的技術(shù)采納曲線是每年都在更新的,在進(jìn)行參考的時候別忘了注意一下發(fā)表的時間。

1.4?根據(jù)開源軟件的成熟度情況選擇開源軟件

還有一點,即根據(jù)開源軟件本身的成熟度來選擇開源。?即從這個開源軟件是否定期發(fā)布,是否處于一個多方維護(hù)的狀態(tài)(即使一個公司的戰(zhàn)略發(fā)生了變化不再繼續(xù)維護(hù)了,還有其他的公司在長期支持),是否文檔比較齊全等多個維度來進(jìn)行成熟度的評估。

對于開源軟件的成熟度模型,開源社區(qū)有很多度量開源項目的成熟度模型,其中?Apache?開源軟件基金會的項目成熟度模型是比較有名的。

可以參考這里:https://community.apache.org/apache-way/apache-project-maturity-model.html

按照這個?Apache?開源軟件基金會制定的開源項目成熟度模型,他把一個開源項目的評估緯度,分為?7?個維度:

Code(代碼)

License and Copyright(軟件許可證和版權(quán))

Release(發(fā)布)

Quality(質(zhì)量)

Community(社區(qū))

Consensus Building(共識共建)

Independence(獨立性)

每個緯度又有幾個考察項。例如針對?Independence(獨立性),又有兩個考察項,其一是看這個項目是否獨立于任何公司或者組織的影響,其二是看貢獻(xiàn)者在社區(qū)內(nèi)活動是代表他們個人,還是作為公司或者組織的代表出現(xiàn)在社區(qū)并進(jìn)行活動的。

Apache?基金會?Top Level?的項目即頂級項目,在畢業(yè)階段都會從這些維度進(jìn)行綜合的判斷。只有各方面都達(dá)標(biāo)的項目,才會被允許從?Apache?基金會的孵化狀態(tài)中畢業(yè)而成為成為?Top Level?的項目。這也是逼著個人比較喜歡?Apache?頂級項目的原因。

另外,OpenSSF?項目的?Criticality?評分(參見https://github.com/ossf/criticality_score)也是一個不錯的參考指標(biāo),它會度量一個項目的社區(qū)貢獻(xiàn)者數(shù)量、提交頻度、發(fā)版頻度、被依賴的數(shù)量等指標(biāo),來判斷一個開源軟件在開源生態(tài)中的重要程度。這里就不詳細(xì)展開了,有興趣的同學(xué)可以參考它的資料,個人認(rèn)為是一個值得參考的方向,但是這個評分還處于早期階段,距離理想狀態(tài)還比較遠(yuǎn)。

1.5?根據(jù)項目的質(zhì)量指標(biāo)來進(jìn)行選擇

很明顯,有些開源軟件的代碼質(zhì)量是比其他開源軟件的質(zhì)量好。?有的時候需要從項目的質(zhì)量情況來選擇開源軟件。

這個時候,我們需要查看一些被業(yè)內(nèi)廣泛證明比較有效的指標(biāo)。

其中?MTTU?是被知名開源供應(yīng)鏈軟件供應(yīng)商?SonaType?所推薦的指標(biāo)。?它在它著名的供應(yīng)鏈年度報告里面提到?MTTU。?參見https://www.sonatype.com/resources/state-of-the-software-supply-chain-2021

MTTU(Mean Time to Update):即開源軟件更新它依賴庫的版本的平均時間。舉個例子來說,某開源軟件?A?依賴于開源庫?B,假設(shè)?A?的當(dāng)前版本是?1.0,依賴?B?的版本是?1.1。某天開源庫?B?的版本從?1.1?升級到了?1.2,然后一段時間之后,開源軟件?A?也發(fā)布了新版本?1.1,其中把對?B?的依賴版本從?1.1?升級到了?1.2。這個時間間隔,即從開源版本?B?的版本升級到?1.2?的時間點距離開源軟件?A?的新版本?1.1?的發(fā)布時間,稱之為?Time to Update,反映出來的是開源軟件?A?的研發(fā)團(tuán)隊,根據(jù)依賴庫的更新周期,同步更新它的依賴版本的能力。Mean Time to Update?是指這個軟件的平均升級時間。數(shù)值越低表明質(zhì)量越好,表明該軟件的負(fù)責(zé)人在很快速的升級各種依賴庫的版本,在及時修復(fù)各種依賴庫引起的安全漏洞問題。

據(jù)?SonaType?的統(tǒng)計,業(yè)內(nèi)開源軟件的更新升級時間?MTTU?越來越短。?據(jù)它的統(tǒng)計,在?Maven?中心倉庫上的?Java?類開源軟件,2011?年平均的?MTTU?為?371?天,2014?年平均的?MTTU?為?302?天,2018?年平均的?MTTU?是?158?天,而?2021?年平均的?MTTU?時間是?28?天。能看出來,隨著開源軟件庫更新頻率的加快,使用它們的軟件也隨著加快了更新版本的速度,MTTU?相對?10?年前,時間縮短到原來的?10/1?以下。

當(dāng)然?MTTU?只有項目質(zhì)量的一個間接緯度。?歷史上是否爆出重要高危安全漏洞,修復(fù)響應(yīng)是否快速及時,等等也是作為開源項目質(zhì)量評價的重要維度。

某些大廠的安全部門,會不斷評估開源軟件的安全情況,把某些屢屢發(fā)生高危安全漏洞,但是修復(fù)不及時的開源軟件設(shè)定為不安全軟件,列入到內(nèi)部的開源軟件黑名單中對內(nèi)公示,并要求各個業(yè)務(wù)研發(fā)團(tuán)隊不再使用這些軟件,實在因為研發(fā)和人力問題不能遷移到新的軟件系統(tǒng)的情況也需要把這些老服務(wù)遷移到一個相對封閉的網(wǎng)絡(luò)環(huán)境中,減少風(fēng)險可能造成的損失。這個時候,顯然應(yīng)該需要遵守公司的安全規(guī)定,不再使用黑名單上的開源軟件。

1.6?從開源軟件所屬于的開源社區(qū)治理模式角度來考慮。

還有一個維度,即從這個開源項目的社區(qū)治理模式來考慮,適用于需要長期進(jìn)行開發(fā)和維護(hù)的項目。

社區(qū)治理模式(Governance Model)主要是指該項目或者社區(qū)是如何做決定的以及由誰來做決定。?具體表現(xiàn)為:?是所有人都可以做貢獻(xiàn)嗎還是少數(shù)幾個??決定是通過投票的方式產(chǎn)生的,還是通過權(quán)威?計劃和討論是否可見?

常見的開源社區(qū)和開源項目的治理模式有如下三種:

單一公司主導(dǎo):特點是軟件的設(shè)計、開發(fā)和發(fā)布都由一個公司來控制,也不接受外部貢獻(xiàn)。開發(fā)計劃和版本計劃不對外公開,相關(guān)討論也不對外公開,版本發(fā)布時候才對外公開源碼。例如?Google?的?Android?系統(tǒng)。

獨裁者主導(dǎo)(有個專有名詞?“Benevolent Dictatorship”,翻譯為?“仁慈的獨裁者”):特點是由一個人來控制項目的發(fā)展,他有強大的影響力和領(lǐng)導(dǎo)力,一般都是該項目的創(chuàng)始人。例如?Linux Kernel?由?Linus Torvalds?來負(fù)責(zé),Python?之前由?Guido Van Rossum?來主導(dǎo)。

董事會主導(dǎo):特點是有一撥人構(gòu)成項目的董事會來決定項目的重大事項。例如?Apache?軟件基金會的項目由該項目的?PMC?決定,CNCF?的基金會的決策是?CNCF?董事會來負(fù)責(zé)(很多技術(shù)決定授權(quán)給了?CNCF?董事會下的技術(shù)監(jiān)督委員會)。

個人意見和經(jīng)驗,根據(jù)該開源軟件背后的開源社區(qū)的治理方式來進(jìn)行選擇優(yōu)先級的排序如下:

優(yōu)先選擇?Apache?畢業(yè)項目(因為這些項目的知識產(chǎn)權(quán)情況清晰,而且至少有三方在長期維護(hù))

次優(yōu)選擇?Linux?基金會等其他開源基金會的重點項目(因為?Linux?基金會的運營能力很強,每個重點項目后面往往都有一個或者多個大公司在支持)

小心選擇一個公司主導(dǎo)的開源項目(因為該企業(yè)的開源戰(zhàn)略隨時可能會調(diào)整,很有可能不再持續(xù)支持該項目,例如?Facebook?就是一個棄坑很多的公司)

盡量不選擇個人開源的項目(個人開源更加隨意,風(fēng)險尤其高,但是不排除某些已經(jīng)有很高知名度,并且跑出長期維護(hù)模式的項目,例如知名開源作者尤雨溪(Evan You)所負(fù)責(zé)的?Vue.js?開源軟件)。

這是個人推薦的選擇同類開源軟件項目的優(yōu)先級順序,僅僅代表個人觀點,歡迎討論。

2.?如何定制和維護(hù)

把一個開源軟件引入到企業(yè)內(nèi)部后并用來進(jìn)行開發(fā)和長期維護(hù),就出現(xiàn)了如何定制和維護(hù)的問題了。?首先要明確,開源軟件引入到企業(yè)內(nèi)部之后是需要定制的。?因為如下幾個理由:

開源軟件往往都是適用于通用場景,考慮的情況比較多,需要支持各種各樣的使用場景。但是引入到企業(yè)內(nèi)部之后,往往只需要針對企業(yè)特定的場景。所以針對這些特定場景進(jìn)行優(yōu)化,例如對全部功能進(jìn)行剪裁,去掉跟本場景無關(guān)的特性,針對特定場景進(jìn)行性能調(diào)優(yōu)和參數(shù)優(yōu)化等,往往能取得更好的性能,例如可以抗更多的流量,節(jié)省機器成本的效果是驚人的。這也是常見的定制方法。

開源軟件進(jìn)入企業(yè)內(nèi)部要經(jīng)過開發(fā)并長期運營,是需要滿足該企業(yè)的各種內(nèi)部的服務(wù)運維規(guī)范的。例如業(yè)務(wù)上線,是需要有完整的日志和監(jiān)控,比如需要提供服務(wù)健康檢查接口,還需要有流量調(diào)度等容錯處理。這些都是需要進(jìn)行定制修改的。

開源軟件還需要對接企業(yè)內(nèi)部的上下游系統(tǒng),例如如果該軟件的正確運行需要依賴底層的分布式存儲和分布式計算系統(tǒng)來完成基本功能,是需要對接企業(yè)內(nèi)部已有的存儲系統(tǒng)或者計算系統(tǒng)的;企業(yè)內(nèi)部的底層虛擬機系統(tǒng)或者容器調(diào)度系統(tǒng),往往有部分修改和優(yōu)化,對接起來也是需要進(jìn)行修改的;所以這個時候需要進(jìn)行定制修改。

特殊場景下的需求定制,在企業(yè)應(yīng)用場景下使用該開源軟件往往會遇到特定的問題,可能會碰到?Bug,這些都需要?Bugfix?和新增特性來支持。

2.1?如何對開源軟件進(jìn)行定制和修改?

對此,筆者建議有幾個基本原則:?不動開源軟件的核心代碼,盡量使用該開源軟件已有的插件機制;或者在外圍改;定期升級到開源社區(qū)的穩(wěn)定版本。

很多開源軟件在設(shè)計之初,就留下了不少擴(kuò)展機制,方便后續(xù)開發(fā)者進(jìn)行功能擴(kuò)展和特性增加。例如幾個最著名的開源軟件?Visual Studio Code,F(xiàn)irefox Browser?就提供了?Extension?機制,很多開發(fā)者根據(jù)自身需求開發(fā)對應(yīng)的插件,并把插件提交到官方支持的插件市場里面。普通用戶在安裝完成主要程序后,還可以瀏覽插件市場,尋找和選擇自己需要的插件進(jìn)行安裝。?另外像?Kubernetes,也在多個地方提供了擴(kuò)展機制,例如核心調(diào)度器哪里提供了定制化的?scheduler,可供開發(fā)個性化的調(diào)度策略;底層的存儲和網(wǎng)絡(luò)都提供了很多的插件機制;最值得稱道的是它提供了?CRD(Custom Resource Definition)的機制,允許開發(fā)者定義新的資源類型,并復(fù)用?Kubernetes?成熟的聲明式?API?和調(diào)度機制,進(jìn)行很方便的操作和運維。?所以,盡量使用該開源項目已有的插件或擴(kuò)展機制來增加特性。

針對某些開源軟件的修改和定制,并不太適合使用它的擴(kuò)展機制,或者它本身沒有提供可用的擴(kuò)展機制。這個時候的修改,盡量在源碼核心的外圍進(jìn)行修改,而不要去動它的核心代碼。因為開源軟件是隨著開源社區(qū)的進(jìn)展不停的迭代的,開源社區(qū)的發(fā)展會不斷帶來更多更好的特性。如果對核心代碼進(jìn)行了修改,而當(dāng)需要升級到比較新的開源版本的時候,就會非常的痛苦。因為有大量的內(nèi)部?Patch?需要進(jìn)行合并,而且需要各種測試,會導(dǎo)致升級成本過高而無法跟社區(qū)的主要版本進(jìn)行同步,最后因為部分核心工程師的離職或者轉(zhuǎn)崗,那部分的修改沒人能持續(xù)維護(hù)下去,導(dǎo)致整個系統(tǒng)無法維護(hù)和升級,最后導(dǎo)致整個系統(tǒng)被廢棄或者被推倒重來,這會導(dǎo)致大量的人力成本。筆者在多家互聯(lián)網(wǎng)大廠工作過很多年,看到了太多這種項目,太多本來針對開源項目的修改,是非常有必要的,但是因為改動了核心代碼,導(dǎo)致想升級到開源社區(qū)的較新版本成本太高,最后導(dǎo)致系統(tǒng)無人能維護(hù),只好推倒重來的例子了。

舉個例子吧,筆者在某大廠內(nèi)部看到有兩個技術(shù)團(tuán)隊在維護(hù)?Redis?集群,當(dāng)時使用的版本都是?Redis 2.x?版本。因為沒有太多集群功能,對大規(guī)模的業(yè)務(wù)支持不好,所以這兩個團(tuán)隊都對?Redis?的?2.X?版本進(jìn)行了修改。其中團(tuán)隊?A?的改法是在外圍改,即在?Redis?之上封裝了一層,用來進(jìn)行流量調(diào)度,F(xiàn)ailover?處理等功能;團(tuán)隊?B?就改的狠一些,直接改?Redis?的核心代碼,把集群功能相關(guān)的代碼直接加了進(jìn)去,甚至在某些局部測試場景下,性能更好一下。短時間內(nèi),兩個團(tuán)隊都能滿足業(yè)務(wù)線的需求。但是?Redis?開源社區(qū)在不停的迭代,不斷加入更多更好的需求,當(dāng)?Redis?出到?3.x?的時候,兩個團(tuán)隊都想升級到比較新的版本,因為使用?Redis?的業(yè)務(wù)方也希望使用?3.x?的版本。但是升級成本明顯不同,團(tuán)隊?A?很快把相關(guān)功能移植到了?3.x?之上,很快把?Redis?版本升級了上去;團(tuán)隊?B?呢,因為對核心的改動太大,移植成本和測試成本都太高,所以遲遲不能對?2.x?版本的服務(wù)進(jìn)行升級。等到社區(qū)?4.x?版本出來,團(tuán)隊?B?的核心工程師離職之后,該?Redis?集群已經(jīng)沒有人能夠持續(xù)維護(hù)并滿足客戶的新版本需求,只好推倒重來,從社區(qū)的?4.X?版本直接建集群,自身的系統(tǒng)遷移化了很長時間,也給客戶帶來了很多成本。

所以,對開源軟件源碼的修改,都建議以?Local Patch(本地補?。┑姆绞酱嬖冢粊肀阌谶M(jìn)行維護(hù)和升級,二來也方便管理和統(tǒng)計。這種模式下,內(nèi)部項目的編譯腳本,一般都是把該開源軟件的某個源碼包解開,然后通過?patch?命令把這些?Local Patch?一一打進(jìn)去,之后再一起進(jìn)行編譯和測試。而不是把?Patch?直接打到業(yè)務(wù)源碼里面,雖然在?CI?階段省了幾分鐘,但是后續(xù)的維護(hù)、升級、管理卻增加了相當(dāng)?shù)穆闊?/p>

2.2?回饋社區(qū),Upstream(回饋)到上游開源社區(qū),減少維護(hù)成本

工程師在企業(yè)內(nèi)部針對某個開源軟件的某個版本,進(jìn)行功能特性的增加或者?Bugfix?之后,一般會以?Local Patch(本地補?。┑姆绞酱嬖谠诖a庫中。筆者建議工程師在解決完業(yè)務(wù)問題之后,盡量把這些?Local Patch?提交到該開源軟件所屬的上游開源社區(qū)里面去,完成?Upstream?的過程。

Upstream?有如下幾個好處:

能獲得更好的代碼

在企業(yè)內(nèi)部針對某開源軟件增加特性尤其是?Bugfix?的補丁,往往因為時間緊急,更多采用的是?“Hack”?的方式,即為了快速上線解決問題,補丁修復(fù)的地方不一定很合理,代碼補丁的邏輯可能會有漏洞,代碼補丁可能對更多異常條件的處理不夠完善等等。這個時候,如果把這個?Local Patch?提回到該開源項目所屬的開源社區(qū)里面,跟該開源社區(qū)的資深工程師(Module Reviewer/?模塊負(fù)責(zé)人)等進(jìn)行深入的溝通交流之后,往往會根據(jù)他們的反饋,對代碼補丁進(jìn)行更好的完善,從而能得到更好的代碼。

能減輕維護(hù)成本

內(nèi)部保留的?Local Patch,在每次升級到開源軟件較新版本的時候,這些?Patch?都是需要進(jìn)行評估,部分需要和入并測試的。當(dāng)然希望這些?Local Patch?的數(shù)量越少越少。最好的辦法就是當(dāng)該開源社區(qū)發(fā)布新版本的時候就已經(jīng)包含了這些?Patch。包含的數(shù)量越多,企業(yè)內(nèi)部需要評估、需要合并和測試的?Local patch?數(shù)量就越少,升級起來成本就越低。記得?Fedora?的發(fā)布版本里面,每個版本都保留了不少針對內(nèi)核和其他組件的?Local Patch,紅帽的工程師也在不斷的把這些?Local Patch?貢獻(xiàn)并和入到上游開源項目社區(qū)里面,這樣才能保持?Fedora?內(nèi)部的?local patch?數(shù)量在一個比較低的水平,也保證了升級版本時候的成本是比較可控的。

建立團(tuán)隊技術(shù)品牌和雇主品牌,方便招聘,并提升工程師自豪感,

向上游開源技術(shù)社區(qū)貢獻(xiàn)代碼,Upstream?這些?Local patch,是可以獲得更好的社區(qū)口碑的。向這些技術(shù)社區(qū)表明該公司不僅只是開源軟件的消費者,同時也是貢獻(xiàn)者。

同時可以建立起較強的團(tuán)隊技術(shù)品牌,表明該公司不僅僅業(yè)務(wù)比較不錯,技術(shù)團(tuán)隊也是很有實力的,這樣方便對外招聘。

Upstream?到上游開源社區(qū),同時也有利于提升團(tuán)隊的工程師自豪感和滿意度。

舉個例子,?小米公司在大量使用?Apache HBase?項目的時候,負(fù)責(zé)的研發(fā)工程師堅決執(zhí)行?Upstream?的策略,不斷的把小米內(nèi)部驗證過的?Patch?貢獻(xiàn)回到?HBase?社區(qū),并和?Hbase?社區(qū)的同學(xué)們一起進(jìn)行某些特性的討論和研發(fā)。小米同學(xué)在?HBase?社區(qū)的影響力越來越大,不斷產(chǎn)生了?Committer?和?PMC,最后小米工程師張鐸成為該項目的?PMC?負(fù)責(zé)人即項目的 PMC Chair。小米公司在大數(shù)據(jù)、云計算等領(lǐng)域的技術(shù)品牌,很大程度上來源于此項目相關(guān)的研發(fā)團(tuán)隊。

3.?個人成長如何利用開源

工程師的成長,跟他從事的日常工作密切相關(guān),也跟他的日常學(xué)習(xí)密切相關(guān)。?在這個過程中,如何利用開源軟件,來更好的幫助工程師進(jìn)行成長,幫助工程師實現(xiàn)他們的職業(yè)理想或者技術(shù)理想,?這里有一些建議。

3.1?開放和共享,眼界和心態(tài)

站住巨人的肩膀上才能站的更高。?開源世界里面有的是各種各樣的軟件,面向各種場景,解決各種問題。?所以一定要保持一個開放的心態(tài),即在做什么技術(shù)相關(guān)的事情之前,先看看別人是怎么做的。?要知道世界這么大,工程師遇到的問題?99.99%?以上都是別人已經(jīng)遇到的問題,別人是如何解決的,有什么經(jīng)驗可以學(xué)習(xí),?尤其是可以看看別人開源出來的項目,看看他們的設(shè)計文檔,看看他們是如何思考的;看看他們的源碼,看看他們是如何實現(xiàn)的。?如果感興趣,還可以進(jìn)一步跟他們直接交流。?一來可以少走很多彎路,避免很多不必要的重復(fù)工作,避免重復(fù)踩坑。?二來不用重復(fù)造輪子,可以把有限的時間放在更有價值的工作上去。?千萬不要坐井觀天,老子天下第一,多看看工業(yè)界和開源界,剛畢業(yè)去大廠的同學(xué)尤其需要注意。

另外還需要共享的心態(tài),學(xué)到了最好能共享出來,?讓別人也能參考,吸取經(jīng)驗和教訓(xùn),從而達(dá)到共同提高的目的。

3.2?學(xué)習(xí)開源軟件的推薦步驟和方法?—?費曼學(xué)習(xí)法

學(xué)習(xí)開源軟件有各種學(xué)習(xí)方法。?針對不同的學(xué)習(xí)目的,也需要根據(jù)自身情況(即對該領(lǐng)域的熟悉程度以及對相關(guān)開源項目的了解程度)等采用不同的更適合自身的學(xué)習(xí)方法。

筆者在這里給大家推薦一個適合工程師學(xué)習(xí)一門全新的開源技術(shù)項目的方法:

先盡快入門,把這個開源軟件的?Quick Start(快速入門)和?Tutorial(入門教程)跑起來,先了解它的主要場景和關(guān)鍵特性。

然后看文檔,注意系統(tǒng)的主要架構(gòu)圖,了解整個系統(tǒng)的大致架構(gòu),建立起一個比較大的整體框架圖出來。

最后再結(jié)合自身的實際應(yīng)用場景看相關(guān)細(xì)節(jié),包括某個細(xì)節(jié)的文檔和代碼。

比如,如果想學(xué)習(xí)?Kubernetes,先上它的官網(wǎng),把它官網(wǎng)上提供的教程快速運行一遍?(https://kubernetes.io/docs/tutorials/kubernetes-basics/create-cluster/cluster-interactive/),?了解如何創(chuàng)建?pod,如何訪問,如何更新,如何進(jìn)行流量調(diào)度等等。?然后看它的架構(gòu)圖,了解它的設(shè)計原則即聲明式編程,包括幾個核心組件?Kube-apiserver,kube-scheduler,kube-controller-manager, kubelet?等的功能以及這些組件都是如何交互的;?最后再根據(jù)自身的業(yè)務(wù)場景需要,看看具體哪部分還需要更深入的了解。?例如需要加入自己的存儲方式,那么看看相關(guān)的代碼,參考其他友商的存儲方式的實現(xiàn)。

不建議一上來先捧著源碼看,這么看是沒有頭緒的,而且效率很低。?況且現(xiàn)在不少開源項目都?Too Big?了,而且迭代速度很快,很難有人能了解全部代碼,而且從個人精力來說做不到,更別說也沒有必要。

注意學(xué)習(xí)一定要和應(yīng)用結(jié)合起來,即要動手。“紙上得來終覺淺,絕知此事要躬行?!?古人云,誠不我欺,對于工程師來說尤其如此。?如果是想比較深入的了解一門新的技術(shù),甚至有打算切換技術(shù)路線和職業(yè)賽道,那么一定要更多的動手,要把這個開源軟件用起來,或者寫一點程序跑個?Demo?并運行在實驗環(huán)境里面,最好解決一些身邊的實際問題。千萬別眼高手低,覺得一切都很簡單,但是真的要跑起來,用起來就千難萬難了??梢試L試參加技術(shù)企業(yè)內(nèi)的一些創(chuàng)新活動,例如?hackthlon(黑客松)活動,把新學(xué)的技術(shù)用起來;或者寫一點點小工具,讓他跑起來,解決一點點實際問題。例如,如果要練習(xí)?Python,寫一個爬蟲,每天去爬天氣預(yù)報網(wǎng)站上的數(shù)據(jù),然后做一個簡單的查詢,可以獲得當(dāng)前的天氣預(yù)報情況。在用中學(xué),學(xué)以致用。

還有一個非常好用的學(xué)習(xí)方法就是費曼學(xué)習(xí)法。費曼學(xué)習(xí)法被認(rèn)為是最有效、最強大的學(xué)習(xí)方法之一,親測管用。?步驟也很簡單,我把它簡化為如下三步。

先學(xué)習(xí)一門技術(shù)

把它講給普通人,讓他聽懂

如果聽眾沒有聽懂,回到第一步

通過這種方法,只有自己講解該項技術(shù)的用法和架構(gòu),并能讓普通工程師聽懂這個技術(shù),才算是真的掌握了。

費曼學(xué)習(xí)法來源于諾貝爾物理獎獲得者理查德?·?費曼(Richard Feynman)。他是一位知名的理論物理學(xué)家,量子電動力學(xué)創(chuàng)始人之一,納米科技之父,因其對量子電動物理學(xué)的貢獻(xiàn)?1965?年獲得諾貝爾物理學(xué)獎。他所提倡的學(xué)習(xí)方法,被稱之為?“費曼學(xué)習(xí)法”。步驟雖然非常簡單,但是能把復(fù)雜的技術(shù)進(jìn)行簡化,并讓普通工程師能聽懂的方式講出來,這需要對這門技術(shù)有深入的理解和掌握,還需要對一些專有名詞和概念進(jìn)行類比、聯(lián)想來進(jìn)行簡化。一般能做到這樣,就說明對這門技術(shù)已經(jīng)達(dá)到了入門的程度,可以繼續(xù)進(jìn)行后續(xù)的更深入的學(xué)習(xí)了。

另外參加業(yè)內(nèi)一些著名課程的考試或者認(rèn)證也是一種比較好的方式。例如對云原生不熟悉的工程師,當(dāng)他通過?CKA(Certificated Kubernetes Adminitrator)認(rèn)證?Kubernetes?管理員考試之后,這個認(rèn)證可以驗證他具備一定的水平,已經(jīng)建立起對?Kubernetes?常見操作和系統(tǒng)架構(gòu)比較全面的了解了。

3.3?融入開源社區(qū),終身個人口碑

最后一點,對于工程師來說,參與和融入到開源社區(qū)里面積極貢獻(xiàn),將會獲得終身的口碑,并能結(jié)交到終身的朋友,是十分有利于工程師的長期發(fā)展的。?在此,鼓勵工程師,可以選擇自己感興趣的開源項目和社區(qū),并通過交流和貢獻(xiàn),不斷在社區(qū)里面成長。即使以后因為工作關(guān)系或者其他種種原因,不繼續(xù)在這個開源項目和社區(qū)中活躍了,但是他的貢獻(xiàn)將一直被承認(rèn)。Apache?開源軟件基金會有一句很有名的座右銘:“Merit never expires”(參見http://theapacheway.com/merit-never-expires/),就是說工程師在?Apache?開源軟件基金會項目和社區(qū)做貢獻(xiàn)獲得的認(rèn)可,是永遠(yuǎn)不會過時的。曾經(jīng)是提交者,永遠(yuǎn)是提交者。

在開源社區(qū)里進(jìn)行協(xié)作,也是工程師進(jìn)行社交的一種方式。在這里,能認(rèn)識終身的朋友,能和他們一起工作和交流,對于工程師的成長也是非常有效的。很多開源社區(qū)的大牛,在社區(qū)里面也是非常友善的,尤其對待新人,對待比較?junior?但是貢獻(xiàn)欲望比較強烈的工程師,更是愿意手把手的教的。在這些大牛工程師的幫助和指引下,新人的成長是非??斓?,而且沒有企業(yè)?/?部門?/?工作項目等帶來的天花板。即新人可以在自己感興趣的開源項目和社區(qū)里面,憑借虛心的態(tài)度和貢獻(xiàn)欲望,不斷和社區(qū)內(nèi)的資深工程師進(jìn)行交流和學(xué)習(xí),可以帶來技術(shù)能力的飛速發(fā)展的。

另外,對于現(xiàn)在的工程師來說,很難有終身雇傭的企業(yè),工程師在企業(yè)里面也就是工作一段時間,然后隨著各種主動或者被動的變化,崗位或者就職企業(yè)也會發(fā)生變化。但是在開源社區(qū)貢獻(xiàn)所獲的認(rèn)可,和建立起來的個人品牌和技術(shù)口碑,是永遠(yuǎn)隨著個人的,不會因為公司或企業(yè)的情況而發(fā)生變動。能看到很多一直活躍在開源社區(qū)的人,雖然職業(yè)發(fā)生了很多變動,但是他們在開源社區(qū)的認(rèn)可和品牌一直存在。這也是很多工程師突破職業(yè)內(nèi)卷,突破平臺限制的一種好辦法。

在開源社區(qū)長期做貢獻(xiàn),是利人利己的好事,鼓勵每一位有想法,有行動的工程師,都能找到自己喜歡并投入的開源項目和社區(qū),并且融入進(jìn)去。

3.4?如何在開源社區(qū)做貢獻(xiàn)

在開源社區(qū),尤其是哪些尊重精英治理的社區(qū)(例如?Apache?基金會的項目),做貢獻(xiàn)越多,得到的認(rèn)可越多。?但是很多時候,作為一個新人,要去開源社區(qū)做貢獻(xiàn),并不是抬抬手就能做的,是需要先了解一些社區(qū)規(guī)則,然后遵守規(guī)則才能夠慢慢融入的。

1.?貢獻(xiàn)什么?

在做貢獻(xiàn)之前,我們需要了解,對開源社區(qū)的貢獻(xiàn)并不是僅僅局限于代碼貢獻(xiàn),寫代碼增加功能或者?Bugfix?是貢獻(xiàn),完善文檔和測試用例是貢獻(xiàn),報告使用問題是貢獻(xiàn),寫博客介紹項目和推薦項目也都是貢獻(xiàn),這些都是在開源社區(qū)內(nèi)被廣泛認(rèn)可的貢獻(xiàn)。

很多社區(qū)的技術(shù)大牛,進(jìn)入開源社區(qū)做貢獻(xiàn)是從提交測試報告開始的。比如當(dāng)年?Mozilla?社區(qū)最年輕的架構(gòu)師?Blake Ross(17?歲就成為?Mozilla?社區(qū)最高技術(shù)決策層之一,并和另外一位架構(gòu)師創(chuàng)立了?Firefox?項目),他最初進(jìn)入?Mozilla?社區(qū),是作為實習(xí)生,從測試開始的。

“Scratch your own itch!”?這是在開源社區(qū)流行很廣的一句話,意思是說在開源社區(qū)做貢獻(xiàn),是需要解決自己的問題的。即在實際工作中遇到了問題,然后嘗試去解決,最后把解決的結(jié)果以社區(qū)接受的方式貢獻(xiàn)到社區(qū)。一般的情況是有個?Bug?或者問題影響用戶的實際應(yīng)用,或者想增加一個新的功能來滿足企業(yè)的自身場景,或者就是想學(xué)習(xí)一些新的技術(shù)。這種解決自身需求的貢獻(xiàn),是比較長久的。而為了一些蠅頭小利,參與社區(qū)運營的一些活動獲取獎勵,對工程師來說只是?for fun,這種貢獻(xiàn)也不是長久的。

所以,對于一個新人,進(jìn)入到開源社區(qū)里面,貢獻(xiàn)可以從一些簡單的問題開始,從解決自身的需要開始。?一個最簡單的例子,先看新手入門文檔,照著文檔描述的步驟一步步走下去,看看能否走通;如果走不通,可以報一個?Bug?出來;或者親身體驗需要增加一些額外的步驟才能走通,可以給這個新手入門文檔提一個?Patch,把這些補充步驟描述出來,這也是社區(qū)很歡迎的貢獻(xiàn)。

有些社區(qū)把一些簡單的?Bug?設(shè)定為?“Good First Issue”,貢獻(xiàn)者可以挑選這些?Issue?來進(jìn)行貢獻(xiàn),來熟悉貢獻(xiàn)流程,并融入到社區(qū)里面。

2.?了解現(xiàn)有社區(qū)情況,尊重社區(qū)的慣例和習(xí)慣

給開源社區(qū)做貢獻(xiàn)的第一步是先了解社區(qū)。

可以通過社區(qū)的網(wǎng)站、郵件列表、Wiki、github?代碼倉庫中的文檔等資料,了解該開源社區(qū)的一些基本情況。

通過查看關(guān)鍵文檔(Contributing.md),了解這些項目的貢獻(xiàn)流程和推薦方法。

注意每個開源社區(qū)都有自己的慣例,比如他們有自己的?Issue?管理系統(tǒng)(有的可能用?github?的?Issue,有的使用?Bugzilla,有的使用?Jira),然后提交?Patch?的流程和要求也不一樣。

例如歷史非常悠久的?Apache HTTP Server?項目,它對貢獻(xiàn)者的要求如下:

Patch?需要符合他們的?Code Style

對代碼質(zhì)量也有一些例如線程安全的要求

Patch?需要針對當(dāng)前的開發(fā)版本?–2.5.X?來做比較

Patch?的格式使用?diff -u file-old.c file.c?來生成

提交?Patch?的入口在?bz.apache.org/bugzilla,建議加上?“PatchAvailable”?關(guān)鍵字

可以在?mail list?中發(fā)郵件來討論,郵件的?title?需要為?[PATCH ]

注意他們采用的方式并不是?github?上流行的?Fork/Pull Request?模式,而是更古老的?Bugzilla+Diff Patch?的模式,?請尊重他們的工作習(xí)慣,使用他們要求的模式。(說句老實話,筆者?20?年前在?Mozilla?社區(qū)做貢獻(xiàn)的時候,工作方式也是采用?Bugzilla + Diff Patch?的方式。二十多年過去了,Apache?的?HTTP Server?項目的工作模式并沒有發(fā)生大的變化。不過工作方式不影響貢獻(xiàn),熟悉并習(xí)慣就好。)

有的開源社區(qū),會提供一種游戲化的貢獻(xiàn)流程,即讓開發(fā)者通過一系列簡單的新手任務(wù)來熟悉項目和貢獻(xiàn)流程。這種方式是對新人更加友好的,也是經(jīng)過該社區(qū)的社區(qū)經(jīng)理精心設(shè)計的。那么對于貢獻(xiàn)者來說,別辜負(fù)了他們的良苦用心,走一遍自己覺得必要的任務(wù),熟悉自己希望熟悉的任務(wù)和流程就好。

3.?態(tài)度需要?“Be Polite and Respectful”,尊重社區(qū)的多樣性

開源社區(qū)里面是充滿多樣性的。

開源社區(qū)內(nèi)大部分的資深工程師對新人非常友好的,他們會很有耐心的教導(dǎo)新人,熟悉文檔,熟悉貢獻(xiàn)流程等等(注意一般只有一次,別辜負(fù)了)。日常交流中,包括在郵件列表中,在?IRC?或者?Slack?頻道中,在?Issue comments?中,都比較?nice。跟他們的溝通和協(xié)作比較容易。

但是注意,也有部分人相對態(tài)度不是特別好,如果遇上了,注意不用發(fā)生正面沖突。建議可以向社區(qū)更資深的一些工程師來求得幫助,而不用正面硬剛。不可能改變?nèi)魏稳?,也不可能讓所有人都喜歡,完成必要的工作就好。

4.?如何快速找到負(fù)責(zé)代碼?Review?的?Module Owner,完成貢獻(xiàn)

有的時候,按照社區(qū)貢獻(xiàn)流程的文檔走下去,不管是提?Issue?或者報?Bugs,發(fā)現(xiàn)模塊負(fù)責(zé)人反饋很慢的時候,這個時候有一些技巧。

可以加入他們的?IRC?或者?Slack?頻道,找到對應(yīng)的模塊負(fù)責(zé)人,然后跟模塊負(fù)責(zé)人進(jìn)行禮貌和有建設(shè)性的對話。

跟他們建立良好的關(guān)系,并通過實際的貢獻(xiàn),逐步建立起他們的信任。

注意,開源社區(qū)的運作是以信任為基礎(chǔ)的。能獲得模塊負(fù)責(zé)人的信任,是非常有利于之后的工作開展的。

5.?提交大?Patch?需要注意步驟

可能有的工程師反饋,我給某某開源社區(qū)提交一個非常好的特性,在我的公司內(nèi)部工作環(huán)境內(nèi)測試并驗證,效果非常好,性能表現(xiàn)非常出色。但是我把代碼提交到上游開源社區(qū)的時候,發(fā)現(xiàn)社區(qū)并不看重這個特性,反而對我的?Patch?指指點點,挑出各種毛病。太麻煩了,太心累了,干脆不貢獻(xiàn)了。

需要將心比心的想象一下,如果一個陌生人給你的項目提交一個很大的?Patch,代碼?Review?實施起來就很費勁,因為?Patch?比較大。雖然貢獻(xiàn)者說這個?Patch?很有用,實現(xiàn)了一股很厲害的功能,而且經(jīng)過了他的驗證,但是他是否可靠,他是否能在社區(qū)里面長期存在,他是否能夠及時修復(fù)他所提交的代碼產(chǎn)生的問題,這些都是問號。所以在沒有建立起基本的信任之前(即提交了幾個小?Patch?并得到了和入),提交大的?Patch?是很費勁的。

另外,提交這個?Patch?的工程師往往并不了解這個開源社區(qū)的歷史,也許這個功能很早就在社區(qū)被討論過了,也許討論的結(jié)論是不需要做或者在別的地方來做。所以,不要盲目自信于自己的?Patch,而是應(yīng)該先跟社區(qū)的工程師先溝通這個場景和問題。

筆者建議貢獻(xiàn)的步驟如下:

如果判斷這個?Patch?比較大,那么先在社區(qū)內(nèi)討論問題,讓社區(qū)認(rèn)可這個問題,同時也能獲得社區(qū)對這個問題的一些歷史信息(如果有的話)

如果社區(qū)認(rèn)可該問題,覺得現(xiàn)在應(yīng)該要修復(fù)了,繼續(xù)討論解決思路

問題和思路已經(jīng)被認(rèn)可之后,并完成一點點設(shè)計之后,再討論具體的代碼?Patch

Patch?需要遵守社區(qū)的規(guī)范(CodeStyle、組件調(diào)用規(guī)范、測試規(guī)范、文檔規(guī)范等)

做好心理準(zhǔn)備,Patch?可能需要反復(fù)修改若干次才能最后被和入,可能需要把一個大的?Patch?拆成若干個小?Patch,分批提交和入。必要的時候需要一定的妥協(xié)。

貢獻(xiàn)一個大的?Patch,實現(xiàn)一個重要的功能,步驟雖然多,時間周期雖然長,但是完成之后,能得到社區(qū)的高度認(rèn)可,往往是成為更高層級貢獻(xiàn)者的基礎(chǔ)。而且對于貢獻(xiàn)者個人來說,內(nèi)心的滿足感和成就感也是非常足的。

6.?注意不要做以下的事情

提出一個?Idea,希望別人來完成。

尤其是剛剛加入一個社區(qū)的時候,就提出社區(qū)需要做某些事情,但是自己不做,希望社區(qū)里面的其他人來完成,這些意見往往是會被忽略的?!坝性S多人,‘下車伊始’,就哇喇哇喇地發(fā)議論,提意見,這也批評,那也指責(zé),其實這種人十個有十個要失敗?!?這種人更是不受社區(qū)歡迎的。

提出一個問題,同時提供一個有建設(shè)性的解決辦法,而且自己要參加,可以邀請社區(qū)其他人來一起。這是比較推薦的做法。

2. 過于急切,缺乏耐心,而忽略了社區(qū)的慣例。

寧可速度慢一點,尤其是在社區(qū)對新人的信任感建立起來之前,要有耐心。筆者曾經(jīng)見過一個剛進(jìn)入開源社區(qū)的工程師,技術(shù)能力很強,但就是只想快點把他的?Patch?和入進(jìn)去。跟模塊負(fù)責(zé)人的溝通的時候,態(tài)度雖然禮貌,但是對負(fù)責(zé)人給出的改進(jìn)意見反應(yīng)很敷衍。折騰過幾次之后,該貢獻(xiàn)者在該社區(qū)的口碑已經(jīng)被損失殆盡,他相關(guān)的?Bugfix?和新功能開發(fā)進(jìn)展很慢,他后來也黯然離開了該項目。

3. 不要碰紅線(即社區(qū)的行為規(guī)范所禁止的一些惡劣行為)

基本每個成熟的開源社區(qū)都有自己的行為規(guī)范(Code of Conduct),一般都會在該社區(qū)網(wǎng)站或者代碼倉庫的顯著位置展示此文件。

規(guī)范內(nèi)容列舉出若干社區(qū)不歡迎的舉動,包括性別、種族、宗教等方面的歧視和冒犯。

注意不要有這些行為,可能有的行為在中國開源社區(qū)里面并不被認(rèn)為是大問題,但是在國際社區(qū)不一定是小事。

7.?在企業(yè)內(nèi)部對上游社區(qū)做貢獻(xiàn)要注意合規(guī)問題

在企業(yè)內(nèi)部給上游社區(qū)做貢獻(xiàn),因為是把公司內(nèi)部研發(fā)的結(jié)果公開出去,所以需要滿足公司內(nèi)部的開源貢獻(xiàn)管理辦法。

每個公司對此的規(guī)定不太一致。例如谷歌鼓勵工程師貢獻(xiàn)到開源社區(qū),但是要求工程師應(yīng)該以?google.com?的郵件地址來進(jìn)行貢獻(xiàn),100?行以下的貢獻(xiàn)不需要通過內(nèi)部流程審批,但前提是項目沒有采用?Google?禁止的許可證(例如?AGPL,Public Domain,CC-BY-NC-*),此外還有一些硬性條件,參見?Google OSPO?的官網(wǎng)鏈接https://opensource.google/documentation/reference/patching。?國內(nèi)百度公司也是鼓勵工程師貢獻(xiàn)到開源社區(qū),無論?Patch?大小都需要經(jīng)過內(nèi)部的電子流程,由該部門的技術(shù)總監(jiān)進(jìn)行審批,并交由百度的開源管理辦公室(OSPO)進(jìn)行備案,以便后續(xù)開源辦公室的數(shù)據(jù)統(tǒng)計和對工程師的貢獻(xiàn)激勵提供數(shù)據(jù)支持等。

在企業(yè)內(nèi)部給上游社區(qū)做貢獻(xiàn)的時候,往往會碰到該社區(qū)要求工程師簽署?CLA(Contribution License Agreement,即貢獻(xiàn)許可協(xié)議)或者?DCO(Developer Certificate of Origin,開發(fā)者原創(chuàng)申明)的事情。其中?CLA?又分為?ICLA(Individual Contributor License Agreement)和?CCLA(Coperation Contribution License Agreement,即企業(yè)級貢獻(xiàn)許可協(xié)議),其中?ICLA?是針對個人的,CCLA?是針對整個企業(yè)的,即如果該企業(yè)簽署了?CCLA?之后,該企業(yè)內(nèi)部的工程師再做貢獻(xiàn)就不用單獨簽署?ICLA?了。不簽署?CLA?的話,則不能提交?Patch。CLA?條款的內(nèi)容是貢獻(xiàn)者把自己的貢獻(xiàn)授權(quán)給社區(qū)來進(jìn)行使用。此時請遵守公司內(nèi)部的規(guī)定,相關(guān)的?CLA?條款可能需要經(jīng)過公司內(nèi)部的法務(wù)來進(jìn)行?Review。不過好在一些著名項目的?CLA?條款,例如?Apache?開源軟件基金會的項目都使用統(tǒng)一的?CLA?文件,CNCF?基金會的項目也是類似。這些著名項目的?CLA?條款,法務(wù)確認(rèn)之后就沒有問題了。如果不是法務(wù)已經(jīng)確認(rèn)過的?CLA,需要跟公司負(fù)責(zé)的法務(wù)進(jìn)行咨詢,避免碰上一些對企業(yè)不利的?CLA。

總結(jié)

本文比較長,凝聚本人的很多心得和體會。

一直認(rèn)為工程師是非常務(wù)實,非常努力的一幫人,是一群深深相信?“我們可以用代碼來改變世界”?的人,是一群認(rèn)為?“Talk is cheap,Show me the code”、“日拱一卒,功不唐捐”?的人。我一直認(rèn)為?“開放、協(xié)作、務(wù)實”?是當(dāng)代工程師最好的特性之一。

在開源世界里學(xué)習(xí)、工作、分享,是工程師改變世界最好的途徑之一。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容