B站Android程式碼庫的演進歷程

android飛魚發表於2019-01-03

早在2012年,B 站 Android APP 便已上線。當時開發者不過一人,而如今,業務線眾多、隸屬不同團隊的Android 端開發人員數以百計。從單兵作戰到百花爭鳴,程式碼庫的組織管理也隨之經過數次的改革、演進。

單倉庫

2014年底,Android 端的常駐開發人員一隻手也數的過來。業務發展迅速,為追求效率,方便管理,所有程式碼都在一個倉庫中,甚至包括第三方的、開源的程式碼(個別用 git submodule 管理)。Clone下來匯入 Eclipse 就可以開幹。

到大約15年中旬,開始使用 Android Studio,得益於 Gradle 的專案管理理念,分出了多個 library module。外部依賴使用 maven。也是這一期間開始搭建了內網 maven 服務。

這期間程式碼庫組織結構是:單倉庫 + 個別 git submodule

 

 

 

這種組織方式好處顯而易見:

  1. 專案結構簡單:隨時隨地 clone 下來匯入 IDE 即可以開始開發,程式碼所有人可見,沒有額外的限制。
  2. 方便快速迭代:改動可以快速入庫,適合小團隊,review方便,改動透明

但是,約莫到16年中,業務發展,新團隊紛紛成立,招聘要求降低人員迅速膨脹。這種小而美的程式碼庫已經不適用了,主要有以下缺點:

  1. 程式碼結構混亂,模組之間依賴關係混沌:倒不如說是技術債,前期的疲於業務迭代,以及沒有及時的規劃出好的程式碼層級架構,如今人員紛雜水平不一,之前追求的“沒有限制”反而誘發了惡果
  2. 編譯時間變長:業務增速發展,程式碼量爆炸式增長,單機編譯越來越慢,開發幸福感跌到谷地

 

 

 

多倉庫

一個字:“拆”。

單倉庫裡,所有能切出去的、划走的,甭管橫的來按業務分、豎的走按層級分,都拆出去,最好倉庫中只留一個光桿app模組,最終只剩下拆無可拆的模組,所有依賴的模組都預先編譯好上傳到maven。期間冠名曰:元件化

 

 

約到17年中,這些拆出來的模組,一些獨立為倉庫,一些按所屬層級聚攏到一起合為一個倉庫。業務模組為了快速除錯,一般會寫一個demo app 模組用作測試。

此時程式碼庫組織結構是:多倉庫

 

 

 

好處是:

  1. 隔離性十足:按業務劃分的模組所屬倉庫,倚托於gitlab許可權管理,“外人”決計無法修改自己的程式碼。
  2. 依賴關係清晰:自上而下,由外而內。更容易做到高內聚低藕合。
  3. 編譯速度快:大部分依賴都預編譯後上傳到maven,比起之前從原始碼編譯的速度不知道快到哪裡去了

但是…

隨著業務線發展、人員的進一步擴張,不到一年時間,多倉庫的缺點也快速暴露了出來:

 

 

 

  1. 維護複雜:尤其是模組之間有依賴關係時,修改依賴版本號是個重要、重複且容易出錯的操作。且不便於review不便於快速暴露修改導致的相容性問題,更進而影響其它模組進度。歷史包袱重,比如由於離職等原因導致責任人丟失,非常難梳理出所有模組的修改歷史,多個團隊協同開發的時候難上加難
  2. 程式碼重複:由於程式碼分散倉庫存放,天然的隔離更容易產生互相拷貝的問題。另外也容易產生相同功能的重複開發,如由不同的人作一個類似的模組,但彼此不知。
  3. 過分隔離:由於團隊的不同,協作工作流程長且所涉人員多,溝通成本非常之高,開會從早到晚,一線開發人員一般只轉注於自己的模組,當一個螺絲釘,無法從專案整體視角看問題,進而又導致專案結構趨於混亂、依賴關係複雜化。

大倉

“大倉”—— 一個來自B站 Go 團隊率先實踐過切實可行的方案映入眼簾。

大倉,來自英文 Monotonic Repository (簡稱monorepo)。望文生義,即一個倉庫,包羅永珍海納百川。源自西方大廠們(Google/Facebook/…)一致叫好的實踐良久的程式碼管理方案。

說到底其實就是一開始的“單倉庫”的進化版。與純粹的“單倉庫”不同的地方是,有眾多的工具鏈來維持大倉的日常開發,而非人力,是工程師文化中“不重複勞動”的極致化體現。

 

 

 

關於大倉,這裡不費篇幅去過多解釋了,請自行 Google

目前(2019/1/3),因為站在巨人的肩膀上,先行者已經準備好了一部分的工具鏈(gitlab-ci, saga等),B站 Android 團隊已基本完成大倉的組建。

依然遵循之前規劃的架構以及元件化的思想,將目錄結構約定為形如:

<root dir>
    ├── app
    │    ├── main
    │    ├── live
    │    ├── bangumi
    │    ├── ...
    │ 
    ├── common
    │    ├── ...
    │
    ├── framework
    │    ├── ...
    │
    └── entrance

依賴關係約定,app -> common -> framework

 

 

 

好處自不必多說,先說其侷限性:

  1. 龐大而臃腫: clone專案和匯入所有程式碼對開發機器是個挑戰(為此我已經更換新款MBP~~)。但可以通過編譯配置以及git sparse-checkout解決
  2. git-flow混亂: 因為之前不同團隊不一樣的git-flow,先天的認知不一,另外個別人對git操作理解不深,會導致出現一些人為因素上的合丟程式碼

對於Android 大倉如何組成,如何解決上述問題,下一篇會給大家分享 歡迎關注

總結

所謂“分久必合,合久必分”,單倉庫也好,多倉庫也罷,都是為了解決業務上的問題而生。

從來沒有放之四海皆準的方案,千萬不要脫離業務談架構,選擇適合自己團隊的方案才是好方案。

早在2012年,B 站 Android APP 便已上線。當時開發者不過一人,而如今,業務線眾多、隸屬不同團隊的Android 端開發人員數以百計。從單兵作戰到百花爭鳴,程式碼庫的組織管理也隨之經過數次的改革、演進。

單倉庫

2014年底,Android 端的常駐開發人員一隻手也數的過來。業務發展迅速,為追求效率,方便管理,所有程式碼都在一個倉庫中,甚至包括第三方的、開源的程式碼(個別用 git submodule 管理)。Clone下來匯入 Eclipse 就可以開幹。

到大約15年中旬,開始使用 Android Studio,得益於 Gradle 的專案管理理念,分出了多個 library module。外部依賴使用 maven。也是這一期間開始搭建了內網 maven 服務。

這期間程式碼庫組織結構是:單倉庫 + 個別 git submodule

 

 

 

這種組織方式好處顯而易見:

  1. 專案結構簡單:隨時隨地 clone 下來匯入 IDE 即可以開始開發,程式碼所有人可見,沒有額外的限制。
  2. 方便快速迭代:改動可以快速入庫,適合小團隊,review方便,改動透明

但是,約莫到16年中,業務發展,新團隊紛紛成立,招聘要求降低人員迅速膨脹。這種小而美的程式碼庫已經不適用了,主要有以下缺點:

  1. 程式碼結構混亂,模組之間依賴關係混沌:倒不如說是技術債,前期的疲於業務迭代,以及沒有及時的規劃出好的程式碼層級架構,如今人員紛雜水平不一,之前追求的“沒有限制”反而誘發了惡果
  2. 編譯時間變長:業務增速發展,程式碼量爆炸式增長,單機編譯越來越慢,開發幸福感跌到谷地

 

 

 

多倉庫

一個字:“拆”。

單倉庫裡,所有能切出去的、划走的,甭管橫的來按業務分、豎的走按層級分,都拆出去,最好倉庫中只留一個光桿app模組,最終只剩下拆無可拆的模組,所有依賴的模組都預先編譯好上傳到maven。期間冠名曰:元件化

 

 

 

約到17年中,這些拆出來的模組,一些獨立為倉庫,一些按所屬層級聚攏到一起合為一個倉庫。業務模組為了快速除錯,一般會寫一個demo app 模組用作測試。

此時程式碼庫組織結構是:多倉庫

 

 

 

好處是:

  1. 隔離性十足:按業務劃分的模組所屬倉庫,倚托於gitlab許可權管理,“外人”決計無法修改自己的程式碼。
  2. 依賴關係清晰:自上而下,由外而內。更容易做到高內聚低藕合。
  3. 編譯速度快:大部分依賴都預編譯後上傳到maven,比起之前從原始碼編譯的速度不知道快到哪裡去了

但是…

隨著業務線發展、人員的進一步擴張,不到一年時間,多倉庫的缺點也快速暴露了出來:

 

 

 

  1. 維護複雜:尤其是模組之間有依賴關係時,修改依賴版本號是個重要、重複且容易出錯的操作。且不便於review不便於快速暴露修改導致的相容性問題,更進而影響其它模組進度。歷史包袱重,比如由於離職等原因導致責任人丟失,非常難梳理出所有模組的修改歷史,多個團隊協同開發的時候難上加難
  2. 程式碼重複:由於程式碼分散倉庫存放,天然的隔離更容易產生互相拷貝的問題。另外也容易產生相同功能的重複開發,如由不同的人作一個類似的模組,但彼此不知。
  3. 過分隔離:由於團隊的不同,協作工作流程長且所涉人員多,溝通成本非常之高,開會從早到晚,一線開發人員一般只轉注於自己的模組,當一個螺絲釘,無法從專案整體視角看問題,進而又導致專案結構趨於混亂、依賴關係複雜化。

大倉

“大倉”—— 一個來自B站 Go 團隊率先實踐過切實可行的方案映入眼簾。

大倉,來自英文 Monotonic Repository (簡稱monorepo)。望文生義,即一個倉庫,包羅永珍海納百川。源自西方大廠們(Google/Facebook/…)一致叫好的實踐良久的程式碼管理方案。

說到底其實就是一開始的“單倉庫”的進化版。與純粹的“單倉庫”不同的地方是,有眾多的工具鏈來維持大倉的日常開發,而非人力,是工程師文化中“不重複勞動”的極致化體現。

 

 

 

關於大倉,這裡不費篇幅去過多解釋了,請自行 Google

目前(2019/1/3),因為站在巨人的肩膀上,先行者已經準備好了一部分的工具鏈(gitlab-ci, saga等),B站 Android 團隊已基本完成大倉的組建。

依然遵循之前規劃的架構以及元件化的思想,將目錄結構約定為形如:

<root dir>
    ├── app
    │    ├── main
    │    ├── live
    │    ├── bangumi
    │    ├── ...
    │ 
    ├── common
    │    ├── ...
    │
    ├── framework
    │    ├── ...
    │
    └── entrance

依賴關係約定,app -> common -> framework

 

 

 

好處自不必多說,先說其侷限性:

  1. 龐大而臃腫: clone專案和匯入所有程式碼對開發機器是個挑戰(為此我已經更換新款MBP~~)。但可以通過編譯配置以及git sparse-checkout解決
  2. git-flow混亂: 因為之前不同團隊不一樣的git-flow,先天的認知不一,另外個別人對git操作理解不深,會導致出現一些人為因素上的合丟程式碼

對於Android 大倉如何組成,如何解決上述問題,下一篇會給大家分享 歡迎關注

總結

所謂“分久必合,合久必分”,單倉庫也好,多倉庫也罷,都是為了解決業務上的問題而生。

從來沒有放之四海皆準的方案,千萬不要脫離業務談架構,選擇適合自己團隊的方案才是好方案。

歡迎加入Android進階交流群;701740775。進群可免費領取一份最新技術大綱和Android進階資料。請備註csdn


相關文章