D項目Android模塊化 VCS演進之路

16年8月底,公司新啟動了一個D項目(代號),從敲下第一行代碼到如今,剛好1個年頭,我們已經在VCS上經歷了多次調整。

第一階段(2016.9 - 2017.2)

在這個階段,開發(fā)同學是2個人,需求快速迭代,此時在一個倉庫上開發(fā),工作流簡單,代碼規(guī)范等約束成本非常低,這也是最舒適的一個階段。

本地feature, 不推遠程,rebase到dev,保持線性,需求變化很快,甚至經常在開發(fā)階段要經常變動,此時線性的git tree的優(yōu)勢非常明顯,快速定位到具體的提交,再執(zhí)行后續(xù)的操作。

第二階段(2017.2 - 2017.4)

在2月份時,團隊成員增長到4個開發(fā)同學(后來在5月份變成5個),因為模塊間沒有一個明顯的界線,所以在開發(fā)時可能會有意、無意的碰到其它模塊的代碼,merge、rebase解決沖突的次數明顯上漲。

此外項目增長到一定規(guī)模,模塊之間存在較嚴重的耦合,同時一些模塊相對于穩(wěn)定,一直存在于主工程并不合適。

更重要的是,任何一處改動都需要編譯整個項目,每次編譯的等待時間都足以讓你懷疑人生。

模塊化勢在必行

Android官方提供一種模塊化方案,即模塊以Module被主工程依賴,第一階段中,我們已經對一些模塊或者Library進行抽離,但是還存在以下問題:

  • 1、 穩(wěn)定的Lib作為Module存在并不合適,每次主工程的編譯都會帶動這些Lib的編譯,導致編譯效率降低,急需將這些Lib上傳到maven,從project依賴轉換為坐標依賴

  • 2、 一些模塊存在于主工程,僅以package分離,我們需要將這些遷移到Module

改造后的架構:

module_v1

還不夠!

  • 1、 即使在做了上面的工作后,依然無法解決模塊的追溯問題,我們只能從整個倉庫的git歷史去追溯模塊的commit,出現問題檢索時,解決速度并不高效

  • 2、 鑒于Gradle的生命周期:同步時,會掃描整個工程.gradle文件并執(zhí)行,即使我只編譯某個子模塊!
    雖然我們基于模塊開發(fā)的效率已經大幅度提高,但是因為上述Gradle的特性,我們依然浪費了一些構建時間

我們決定一步到位,將子模塊全部遷移到獨立倉庫中!
每個模塊保證有獨立的追溯歷史,模塊測試放到獨立的倉庫里進行。

這樣遷移后,項目架構如下:


module_v2

理想很豐滿,現實很骨感

在遷移后,我們的工作流轉變成:
開發(fā)feature時,會在對應子模塊工程里開發(fā),然后發(fā)布到maven,主工程依賴新的子模塊坐標。

如上的工作流其實沒有什么問題,但是:

  • 1、 因為我們App體量并沒有足夠的大,業(yè)務雖然沒有16年時變動那么大,但是還是常有跨多模塊的需求,這種情況下,我們多是在主工程來測試的,如果過程有問題,就需要子模塊重新發(fā)布,主工程重新同步、編譯,而Andorid的同步速度大家是知道,如果開發(fā)額不夠順利,上面的步驟會多次重復...

  • 2、 團隊4個開發(fā)同學,但是算上主工程有8個業(yè)務模塊,平均1個人對應2個模塊,這種規(guī)模之下,把所以子模塊都遷移到獨立倉庫后,維護成本真的很高,模塊的完全解耦,讓開發(fā)同學感到不適

  • 3、 檢索代碼麻煩,主工程因為是坐標依賴,想搜索模塊的代碼,或者搜索某個方法的調用鏈都成為非常麻煩的事,而打開對應模塊工程去搜索,耗時且麻煩

  • 4、 很多情況我們需要一起切換分支或者一起checkout到某一個commit節(jié)點,之前在一個倉庫時checkout即可,但現在多個倉庫很頭痛

以上導致一個比較嚴重的問題:代碼沒有很好的在可控范圍內,Review代碼,查找BUG等都變得困難。

第三階段(2017.4 - 至今)

為了解決上面的痛點,我們找到2個東西: Repo,Git Submodule

Repo

Repo是Google管理Android源碼的工具,是基于Git之上的構建工具,可以看作是Git的Wrapper,它提供一些命令集來操作其關聯的模塊。它引入一個Repo的角色來管理各個倉庫,這意味著主工程和子模塊是同等地位的。

使用Repo的話,模塊關系如下:

Repo

這樣的話,開發(fā)方式和之前沒有任何區(qū)別,依然是子模塊發(fā)布maven,主工程坐標依賴,來保證主工程和子模塊的版本關系。
Repo只是幫我們打包了多倉庫的 檢出、切換等Git命令,并沒有很好的解決上面提到的問題,所以Repo目前并不能解決我們的痛點,現階段并不適合我們。

Git Submodule:

Git Submodule是Git提供的功能,它允許你將一個 Git 倉庫作為另一個 Git 倉庫的子目錄,它能讓你將另一個倉庫克隆到自己的項目中,同時還保持提交的獨立。

在Submodule中,當子模塊的倉庫有新的commit時,主倉庫就會產生一個該模塊的SHA值改變,該SHA值紀錄了子模塊的對應commit,以此來連接宿主關系。

使用Git Submodule的話,模塊關系如下:

Git Submodule

這個關系圖太熟悉了,不正是Android標準模塊化的關系圖嗎?!所以我們決定在這個看似很完美的方案上摸索。

在經過Git Submodule的改造后,架構圖如下:

module_v3

在經歷一段適應期后,會發(fā)現Git Submodule的設計還是非常智慧的,但不可否認,不經任何裝飾的Git Submodule直接用到App的工作流中,還是挺坑的。

比如當你主工程檢出分支到某個commit時,子模塊并不跟隨切換到對應模塊,需要手動執(zhí)行 submodule update命令來讓子模塊切換到對應commit,但是這些更新后的子模塊會在游離的HEAD上,在該狀態(tài)上的commit是沒有意義的。

除此之外還有很多其它的坑,如果讓團隊成員每個人都搞懂這套繁瑣的機制并不現實,同時多倉庫的存在讓Git flow也繁瑣很多,所以為了解決這些問題,我提供了一個腳本命令工具:ggsm

ggsm

ggsm可以看做是Repo + Git Flow的集合,它提供一些命令,可以方便打包操作多倉庫,目標是像操作一個Git倉庫一樣操作主工程以及其Submodules,而目前我們確實也做到了。

ggsm

ggsm是Git Submodule的Wrapper,它并不會影響我們平時的開發(fā)習慣,你依舊在某個倉庫里add ,commit - 當你要開發(fā)某個feature時,start命令幫你把所有倉庫都切換到新的feature分支,當子模塊都開發(fā)完成后,主工程里提交對應子模塊的SHA(類似上傳maven,主工程依賴新的坐標),然后使用merge finish推送代碼到遠程倉庫,最后通過mr命令提交MR。

可以看到 我們把Repo和Git Flow集成在一起了,這樣團隊成員對Git Submodule幾乎是無感知的,同時git flow也規(guī)范化了。

可以做的更多

事實上,ggsm承載了更多的功能:

  • 1、 容錯處理機制,檢測模塊commit的完整性

  • 2、 Git hooks,鉤子的更新、安裝都放到了ggsm內,這一過程透明,目前我們做了commit msg檢查、代碼規(guī)范檢查

  • 3、CodeReview,目前我們把Merge Request也集成到ggsm里,這樣開發(fā)同學完成某個feature后會自動通過GitLab API創(chuàng)建MR,發(fā)送郵件通知等

關于Repo和Git Submodule

如果你的項目各個模塊非常獨立,體量也比較大的話,Repo是非常好的管理工具,總之:

沒有最好的方案,只有更適合的方案

軟鏈接

我們使用了軟鏈接,它將子模塊的Module軟鏈接帶主工程內,從而可以使用Project依賴。
在開發(fā)跨模塊的需求上Project依賴會讓你的開發(fā)效率大幅度提高,對于單一模塊的需求,我們打開對應的子模塊直接在其內開發(fā)即可。


軟鏈接

未來

我們所做的一切,都是為了在 高可維護性和開發(fā)舒適性 上找到一個更好的平衡點。

對待子模塊,我們并不拘泥于一種形式,比如 MsgPay這2個子模塊是比較穩(wěn)定的,那么這2個模塊倉庫就完全不需要使用Git Submodule關聯,使用坐標依賴。

模塊足夠獨立或穩(wěn)定的時候,Git Submodule是多余的,反而會拖慢集成主工程時的效率。

此外目前的階段有足夠的靈活性,未來某個模塊足夠穩(wěn)定或獨立時,rm -rf submodule就可以解除宿主Git Submodule關系,轉變?yōu)樽鴺艘蕾嚰纯伞?/p>

目前來看當前的VCS以及模塊化方案已經算是一個很好的平衡點,足以應對當前階段的D項目。

未來我們也會繼續(xù)在VCS、工作流、自動化等方面做更深入的探索。

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

相關閱讀更多精彩內容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,319評論 25 708
  • 開發(fā)中我們經常會遇到這樣的情況:項目越來越大,一些通用的模塊我們希望將他抽離出來作為單獨的項目,以便其他項目也可以...
    feil0n9wan9閱讀 20,636評論 0 24
  • 2017.4.14 回家終于有時間去小吃街一趟,一直人多,終于擠進來一趟了。
    陳如一閱讀 348評論 0 0
  • 她 生于漢朝,逝于漢朝 卻比她的朝代存在得更久 她在古墓里沉睡了幾千年 她的朝代卻早已滅亡 也許 她早已料到她的朝...
    三湘漣漪閱讀 1,066評論 3 5
  • 隨著生活節(jié)奏的加快和工作壓力的加大,不少人的胃都處于亞健康狀態(tài),并不是自己想像的那樣健康。得了胃病,一定要選擇正規(guī)...
    東垣養(yǎng)生閱讀 782評論 0 0

友情鏈接更多精彩內容