Google 和騰訊爲什麼都採用主幹開發模式?
1 摘要
本文介紹了兩種常用的代碼分支模式:特性分支開發模式、主幹開發模式,分別闡述了其優缺點和適用環境;同時剖析了 Google 和騰訊採用主幹開發模式的背景和決策因素,捎帶分享了這 2 個巨頭的實踐,供讀者在技術選型中參考。
2 背景
按之前的寫作思路,本文應該叫《Google 工程效能三板斧之三:主幹開發》,但我改變了主意,希望能同時提供國內互聯網公司的實踐,供讀者參考,因此文章標題也隨之更改。
軟件開發過程中,開發人員通過版本管理工具對源碼進行存儲,追蹤目錄和文件的修改歷史。爲了區隔不同狀態的源代碼,會採用分支進行管理。不同的軟件開發模式,對應着不同的分支模式。
軟件業界常用的軟件分支模式有多種,但本質上可以分爲兩類:
-
主幹開發模式(Trunk Based Development)
-
特性分支開發模式(Feature Branch Development)
3 兩種模式的定義及優缺點分析
特性分支開發模式
特性分支開發模式是指爲一個或多個特定的需求 / 缺陷 / 任務創建代碼分支(branch),在其上完成相應的開發(一般經過增量測試)後,把它合併(merge)到主幹 / 集成分支的開發模式。
通常這種分支生命期會持續一段時間,從幾天到幾周不等,極少數情況甚至以月算。
特性分支開發模式中常用的有 Git-Flow 模式、Github-Flow 模式和 Gitlab-Flow 模式等。這些模式只有細節上的差異,以 Git-Flow 爲例:
優點:
-
特性開發週期寬鬆:因爲生命期可以較長,較大的需求特性可以在寬鬆的時間內完成再合入主幹;
-
分支測試的時間寬鬆:因爲生命期可以較長,可以有較多時間對分支進行測試,甚至手工測試;
缺點:
-
分支管理複雜:原因在於大量採用代碼分支,且來源分支和合入目標分支各異,操作複雜 —— 以上圖爲例,可以從 master(Tag 1.0.0) 拉出 hotfix 1.0.2 分支,然後合入到 develop 分支,開發階段結束後合入到 release branches,發佈後合入 master,非常複雜,很容易出錯;
-
合併衝突多、解決難:分支生命期越長,意味着與主幹的代碼差異越大,衝突概率越高,衝突的解決難度越大(甚至成爲不可能);
-
迭代速度慢:特性分支生命期長(數天至數週)意味着特性上線速度慢,相應的迭代速度也慢;
-
需要較多測試環境:每個特性分支都需要分配至少 1 個測試環境,且長期佔用(有狀態);
適用環境:
-
對版本迭代速度要求不高
-
測試自動化程度低,或說主要靠人工測試的
主幹開發模式
主幹開發,是指開發人員直接向主幹(習慣上主幹分支通常爲:trunk 或 master)提交 / 推送代碼。通常,開發團隊的成員 1 天至少 1 次地將代碼提交到主幹分支。在到達發佈條件時,從主幹拉出發佈分支(通常爲 release),用於發佈。若發現缺陷,直接在主幹上修復,並根據需要 cherry pick 到對應版本的發佈分支。
流程:
優點:
-
分支模型簡單高效,開發人員易於掌握不容易出現錯誤操作
-
避免了分支合併、衝突解決的困擾
-
隨時擁有可發佈的版本
-
有利於持續集成和持續交付
缺點:
-
基礎架構要求高:合入到主幹的代碼若質量不過關將直接阻塞整個團隊的開發工作,因此需要高效的持續集成平臺進行把關;
-
自動化測試要求高:需有完備單元測試代碼,確保在代碼合入主幹前能在獲得快速和可靠的質量反饋;
-
最好有代碼評審:若代碼質量要求高,需要配套代碼評審(CR)機制,在代碼提交到主幹時,觸發 CR,通過 Peer Review 後才能正式合入;
-
最好有特性開關:主幹開發頻發合入主幹的情況下,特性拆分得很小,可能是半成品特性,需要配套特性開關(Feature Toggle),只有當特性整體開發完才通過灰度發佈等手段逐步打開;
適用環境:
-
對迭代速度要求高,希望需求快速交付上線
-
基礎架構強,持續集成工具高效;
-
團隊成員習慣 TDD(測試驅動開發),代碼自動化測試覆蓋率高(至少增量代碼的自動化測試覆蓋率高);
4 爲什麼 Google 和騰訊採用主幹開發模式
互聯網巨頭 Google 大部分業務開發都採用主幹開發模式,國內巨頭騰訊也在推行主幹開發(試點業務團隊大部分已經採用)。
他們採用主幹開發的原因在於對主幹開發的優點有強烈訴求,而且有能力和資源彌補其缺點:
-
都是互聯網企業,競爭激烈,因此對迭代速度要求高;
-
基礎架構能力強:都能自研強大的持續集成平臺,Google 有自研的 Forge,騰訊有自研的藍盾;
-
自動化測試能力強:都推行 TDD,強調開發負責質量,減少甚至取消手工測試人員(少量必要的手工測試轉外包),自動化測試覆蓋率高;
-
都有嚴格的 CR 機制確保代碼質量:Google 極其嚴苛的可讀性認證(Readability)在業界已經是標杆,騰訊是國內少有正在採用類似實踐的互聯網企業。嚴格的代碼可讀性認證和根據此標準執行的嚴格代碼評審制度,能有效的保證合入主幹的代碼質量不會降低。
主幹開發的最大優點是:效率和質量,而這 2 者是軟件和互聯網企業的核心訴求。主幹開發的缺點,巨頭有能力和資源來填平這些坑。
因此,從 ROI(Ratio of Investment)的角度來看,Google 和騰訊採用主幹開發實屬必然。
5 美中兩巨頭的實踐
Google 在主幹開發的實踐
我們在之前的文章提到,Google 的工程效能(也叫研發效能)核心理念只有簡單的 3 條:
-
使用單體代碼倉庫(參考:Google 工程效能三板斧之一:單體代碼倉庫)
-
使用 Bazel 構建(參考:Google 工程效能三板斧之二:使用 Bazel 構建)
-
主幹開發;
其中的第 3 條,就是本文所述內容。
爲了保證主幹代碼的質量,避免出現工程師合入到主幹的代碼 break 掉主幹的情況,Google 採取了以下實踐:
-
代碼合入事件觸發通過持續集成,確保合入到主幹的代碼經過充分且必要測試;
-
通過 Bazel 實現相關代碼(指依賴變更代碼的代碼)的精準測試;
-
至少 2 個合資格的 reviewer (代碼評審人)的 LGTM(Look Good To Me),才允許代碼合入主幹;
-
合資格的 reviewer 都是在 Google 內部通過 Readability (代碼可讀性)認證的員工;
騰訊在主幹開發的實踐
騰訊某 BG 在 2018 年開始的 “930 變革” 後,在各試點團隊推動主幹開發(注:並未全公司普遍採用),具體的舉措包括:
-
以度量牽引:通過對特性分支)的生命期監控和預警,實現非主幹分支的生命期縮短,倒逼開發團隊採用主幹開發;
-
投大力氣統一 BG 內的持續集成工具、開發自動化測試平臺;
-
制定了 7 大編程語言的編碼規範,並自研代碼靜態掃描工具;
-
並參考 Google 推行代碼可讀性(Readability)、可測試性(Testability)認證制度;
-
強力推行 CR (代碼評審)制度,確保代碼的可讀性(命名、代碼風格、設計、複雜度)。
效果:
-
質量提升:代碼質量從可測量的維度得到明顯提升(代碼規範率、單元測試覆蓋率);
-
迭代速度提升:試點團隊的迭代週期從 4 周或 2 周提升至 1 周;
-
代碼從 “私有” 變“公有”:通過代碼評審制度,提高了代碼可讀性,使代碼從個人擁有(只有寫代碼的人能看懂),變成團隊擁有(整個團隊都能看懂);這一點對於企業非常重要,接手過別人代碼的程序們都有感受;
-
代碼的自動化測試覆蓋率提升明顯,爲未來的重構構築了一張安全網;
6 中小企業能參考什麼?
中小企業應該選擇特性分支開發模式,還是主幹開發模式?根據上文,相信大家已經足以自行判斷。
有些中小企業的技術決策者非常認可持續集成 / 持續交付的理念,從而更希望採用主幹開發,但對於主幹開發的缺點(或說彌補缺點的成本)存在顧慮。
對此,我有如下建議:
-
基礎架構要求:可以考慮採用開源軟件,如持續集成採用 Jenkins、Travis CI、Gitlab CI 等,通過簡單部署可以投入使用;同時配合代碼靜態分析工具(如 SonarQube、CheckStyle),確保代碼基本質量過關;
-
自動化測試要求:工具上不存在障礙,現代編程語言(如 java、go、c++)都有內建或第三方的單元測試框架;難點只在於成員的開發習慣,可以通過測試覆蓋率工具,以增量覆蓋率指標保證新增代碼都有完備的自動化測試,從而逐步改變團隊的研發文化;
-
代碼評審要求:開源的 Git 服務器(如 Gitlab)基本都支持 push hook,配合開源的 Gerrit 等 CR 工具,可以實現在代碼推送(push)或 pull request(合入請求)時觸發 1 個代碼評審請求,實現評審通過後,代碼才正式合入的功能;剩下的就是研發文化問題了,需要在團隊內部推行代碼規範、代碼可讀性等宣導和教育工作;
-
發佈時的特性開關:如果要求不高,可以通過代碼 hard code 一個常量作爲特性開關;如果要求高,也有開源的特性開關(比如:unleash、piranha、flipper)工具可供選擇。參考上述建議,並充分認識到主幹開發的成本和困難的情況下,中小企業開發團隊也並非不可以考慮主幹開發的實踐。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/RWDuzT87LlJvj6P_JEjvGQ