根據谷歌對外公布的數據,它的20億行代碼都部署在同一個代碼倉庫里,通過基于基線的方式進行開發(fā)工作中的代碼共享。
從上面這張圖可以看到,一共有文件10億個,源文件數量達到900萬個,源代碼行數達到20億行,提交代碼的深度可以挖掘到3500萬次提交,平均每個工作日提交4萬次,數字真是恐怖。
從大眾的眼光來看,特別是那些谷歌公司外部的人,他們會覺得這種單一代碼倉庫的管理方式,尤其是代碼量這么恐怖的前提下,這種管理方式很不正常,但是它真的很有效,而這種有效是由管理方式決定的,而不是單純讓它自然生長。
Rachel Potvin和Josh Levenberg編寫的一篇文章里是這么描述的:
谷歌的代碼庫由全球數十個辦公的超過2.5萬名軟件開發(fā)工程師所共享,平均每天他們會提交1.6萬次代碼修改請求,全文地址可以點擊這里。
只有一個版本
正如下面這張圖所顯示的,在谷歌,你看不到代碼分支,拉代碼分支是很多公司的習慣做法,在開發(fā)階段這個很方便,相當于一個個獨立的Docker鏡像,但是等代碼合并的時候就不是這么好玩了。
對于只有一個源碼倉庫的開發(fā)模式來說,你不可能出現應用程序FooBar使用AngularDartV2.2.1版本,而另一個應用程序BarFoo使用2.3.0版本的情況。兩個應用程序必定需要使用同一個版本。這其實是將多版本之間的完全兼容性測試由出現問題轉移到了代碼提交環(huán)節(jié)。
每次提交74000個測試用例
我們這里以AngularDart框架為例,它目前有1601個測試用例。當你向谷歌的代碼庫提交一次AngularDart代碼時,會自動為所有依賴于AngularDart框架的工程運行測試用例。也就是說,差不多有74000個測試用例(視依賴的工程數量而定,這里只是舉一個例子,有些流行的框架可能測試用例會更多)。
我們舉個例子,也許你修改代碼的數量很少,例如“&& random.nextDouble() > .05”,你只是增加了這么一個判斷條件,它并沒有觸發(fā)1601個測試用例里面的任何一條,但是因為你增加了這個判斷,它可能會對框架的使用方造成問題。
真正的價值在于,提交代碼時所作的測試時針對真實的應用程序的。不僅僅測試的量級很大,針對使用方的測試也可以反應你的框架是如何被開發(fā)者所使用的。這就好比我們自己寫框架的人,寫出來的測試用例都是符合我們思考方式的,但是你無法左右你的客戶如何使用你。
對于生產環(huán)境下的應用程序,我們應該明白它們和測試環(huán)境的示例程序存在巨大的區(qū)別,你當前支撐得好,他們才會一直使用下去,這種做法也是為了更好地支持后續(xù)的開發(fā)活動。
你制造麻煩,你修復它
正如標題所說,如果AngularDart的作者引入了一個改變,哪怕只是一行代碼的改變,他們都需要直接去為客戶解決問題。也正是由于谷歌只有一個代碼庫,所以AngularDart作者可以直接修復問題。
所有的修改代碼和針對客戶的修復措施代碼,它們都需要同時被提交帶代碼庫,當然,還需要所有相關方的代碼評審完成之后才能提交。
我們舉個例子。當AugularDart團隊的成員想要做代碼修改,而這次的代碼修改會影響AdWords這個應用程序的代碼,那么AugularDart團隊的成員需要直接進入AdWords的源代碼,然后修復問題。他們可以運行AdWords已存在的測試用例,也可以自己增加一些新的用例。然后他們把所有的改變寫入改變列表(change list)并提交評審。因為他們的change list涉及到框架(AngularDart)和調用方(AdWords)的代碼,所以系統(tǒng)會自動請求來自雙方面的成員進行代碼代碼審核和批準請求。
當然,業(yè)界也有其他的批評,認為AngularDart開發(fā)者僅關注了谷歌內部的使用方,例如AdWords,而沒有關注外部的使用方,例如Workivas、Wrikes,以及StableKernels。
大規(guī)模改變
如果AngularDart準備進行一次大規(guī)模的改變,例如從2.x升級到3.0,是否真的需要為所有的使用者(框架依賴方)修復缺陷、運行測試用例,答案是:Yes。
當類Foo里的一個方法從bar()變?yōu)閎az(),你可以構建一個工具,這個工具可以遍歷整個Google代碼庫,自動搜索所有的Foo類及其子類的實例,直接把它們修改為baz()。
性能指標
除了關注功能,谷歌還要求框架提供方關注提交代碼后出現的性能問題。谷歌會自動為每一個使用方生成性能測試結果,這個性能測試是針對生產環(huán)境的,絕對真實。
Hermetic構建工具
對于大量的測試用例,開發(fā)人員當然不可能一個一個去運行,一個個修復缺陷,他們使用的是Bazel(開源構建代碼工具)。在這個量級下你不可能使用一系列的shell腳本構建工程,你需要的是hermetic構建工具。
hermetic在這里的意思有點類似于“純正”,你構建的步驟不能有單邊影響(例如temo files、changes to PATH這些修改),修改需要是可以判斷的(例如輸入什么導致輸入改變)。你可以在自己的機器上通過hermetic工具先運行測試用例,相當于你機器上的客戶端,運行通過后把改變代碼提交到服務器上并行構建它們。
總結
通過這種類似于提供方作為責任方的制度,讓谷歌的軟件開發(fā)人員對于每一行代碼的提交都會非常謹慎,但是也對生產環(huán)境的程序穩(wěn)定性、性能提供了充分的保障,此外,通過這種方式也會影響開發(fā)人員對于產品的開發(fā)思維,讓他們可以站在用戶的立場上思考如何更好地構建自己的框架,這其實也是在一定程度上推動技術和產品的發(fā)展。