青團社業(yè)務發(fā)展愈發(fā)多樣,Android使用模塊化設(shè)計進行業(yè)務的解耦,在代碼都解耦上我們已經(jīng)有一套方案胖腾,但在工程的模塊化設(shè)計上烟零,還缺少一個成熟的方案瘪松。
在前期模式過程中,我們在component_task模塊上率先進行了嘗試锨阿,結(jié)合當時的需求和場景宵睦,我們使用率git submodule和pin工程來實現(xiàn)task工程的管理。
- git submodule 將代碼都版本管理從主工程中抽離墅诡,實現(xiàn)在多個主工程中代碼的同步
- pin工程 細化業(yè)務粒度壳嚎,實現(xiàn)不同flavor下的特定代碼實現(xiàn)
改設(shè)計上開發(fā)一段時間后,git submodule暴露了一些問題:
- 學習成本末早,需要學習git submodule的一些命令和思想烟馅,尤其是commit id的概念
- 代碼穩(wěn)定性不可靠,主工程對task的依賴實際是通過commit id進行依賴然磷,多人開發(fā)下會出現(xiàn)下拉代碼郑趁,commit id并不會自動去更新本地的task工程,因此可能會導致未處理的情況下提交代碼覆蓋了線上的最新commit id
雖然在生產(chǎn)環(huán)境下會對commit id進行校驗姿搜,但獨立主工程的版本管理寡润,版本號的缺失,以及維護成本確實對開發(fā)不夠友好舅柜。
為了提高代碼穩(wěn)定性梭纹,設(shè)計了一套新的依賴管理,在效率上較submodule低一些致份,但代碼穩(wěn)定性有很大的保障变抽,責任劃分也更加明確。
gradle中的依賴
gradle中主要有三種依賴類型
- module
- project
- file
module依賴最簡潔知举,只需要將對應的倉庫路徑添加進去即可:
implementation 'com.google.code.gson:gson:2.8.5'
project需要配置setting和build文件
在開發(fā)期會傾向于使用project對業(yè)務模塊進行開發(fā)瞬沦,在打包或者不需要開發(fā)的模塊使用module依賴方式,手動配置需要改動多個文件雇锡,效率低逛钻。
QDepend
一鍵切換依賴模式,確保生產(chǎn)環(huán)境aar版本依賴锰提,開發(fā)環(huán)境動態(tài)依賴
對整個切換邏輯進行封裝曙痘,作為一個plugin添加到maven中,方便實用立肘。
Android Stuido中傳統(tǒng)的多module工程結(jié)構(gòu)如下:
├── app
├── component_jobs
├── component_login
├── component_me
QDepend改造后的工程边坤,將原有的module抽離,工程中只含有一個app主module谅年,內(nèi)部提供maven依賴各個模塊
├── app
module作為單獨的component庫茧痒,有獨立的git管理,默認的目錄結(jié)構(gòu)是與工程平級
├── DrinkWater
│ └── app
├── component_jobs
├── component_login
├── component_me
在切換maven依賴和本地project依賴時融蹂,只需配置module_map.properties中的開關(guān)位即可
使用
在一個新的工程中旺订,我們需要手動適配QDepend插件弄企,進行如下操作:
- 在gradle/depend目錄下添加module_map.json
- 工程目錄下添加module_map.properties
- setting.gradle添加com.qtshe.setting插件
- app/build.gradle添加com.qtshe.depend插件
改造流程
1.添加module_map.json
module_map.json按照特定的數(shù)據(jù)格式配置,添加需要動態(tài)控制的module
{
"libs": [
{
"name": "homepage",
"group": "com.qtshe.mobile.component",
"path": "../component_homepage"
},
{
"name": "me",
"group": "com.qtshe.mobile.component",
"path": "../component_me"
}
]
}
其中:
- name: 對應的module project名
- group: 在maven中g(shù)roup字段
- path: 本地的module路徑
比如gson的依賴:
implementation 'com.google.code.gson:gson:2.8.5'
name:com.google.code.gson
group:gson
2.添加module_map.properties
module_map.properties作為動態(tài)依賴的開關(guān)区拳,把需要的module name設(shè)置為true即可拘领,注意必須在json中存在:
homepage = false
me = true
以上會對me模塊替換成本地依賴
3.setting.gradle修改
需要引入plugin挽霉,注意setting不屬于build script亩冬,所以要單獨添加classpath
include ':QtsCustomer'
buildscript {
repositories {
maven { url "http://xxxx/nexus/content/repositories/releases/" }
maven { url "http://xxxx/nexus/content/repositories/snapshots/" }
google()
jcenter()
}
dependencies {
classpath 'com.qtshe.mobile:dependencies:1.1.1-SNAPSHOT'
classpath 'com.google.code.gson:gson:2.8.5'
}
}
apply plugin:"com.qtshe.setting"
4.build.gradle
因為要使用插件,所以需要在根目錄的build.gradle中添加classpath
buildscript {
repositories {
maven { url "http://xxxx/nexus/content/repositories/releases/" }
maven { url "http://xxxx/nexus/content/repositories/snapshots/" }
google()
jcenter()
……
}
dependencies {
……
classpath 'com.qtshe.mobile:dependencies:1.1.1-SNAPSHOT'
classpath 'com.google.code.gson:gson:2.8.5'
}
}
同時在build.gradle中應用插件
apply plugin: "com.qtshe.depend"
適配好后只需要修改module_map.properties就可以實現(xiàn)切換
依賴庫的管理
一個完整的maven依賴包含group贝攒,module笆凌,version三部分圣猎。
模塊化開發(fā)中規(guī)范如下:
- 所有都component都以com.qtshe.mobile.component作為group。
- module命名以flavor-module格式菩颖,如趣喝水的login模塊:drinkwater-login
- 開發(fā)版:DEV-SNAPSHOT样漆;正式版:verison_name.xx 如趣喝水login:1.0.0.1
開發(fā)模式
開發(fā)階段會涉及到頻繁的修改代碼,本地開發(fā)時可以通過QDepend切換本地模式即可晦闰,但實際情況往往是多人協(xié)助開發(fā)放祟,以及提測時jenkins上不斷的修復bug更新代碼,因此開發(fā)模式可以將依賴改為snapshot模式呻右,以下是趣喝水開發(fā)階段的component依賴:
implementation 'com.qtshe.mobile.component:drinkwater-common:1.0.6'
implementation ('com.qtshe.mobile.component:drinkwater-login:DEV-SNAPSHOT'){
exclude group:'com.qtshe.mobile.component', module:'drinkwater-common'
}
implementation ('com.qtshe.mobile.component:drinkwater-me:DEV-SNAPSHOT'){
exclude group:'com.qtshe.mobile.component', module:'drinkwater-common'
}
implementation ('com.qtshe.mobile.component:drinkwater-jobs:DEV-SNAPSHOT'){
exclude group:'com.qtshe.mobile.component', module:'drinkwater-common'
}
SNAPSHOT會在每次下拉代碼時拉取最新的依賴跪妥,保證協(xié)助開發(fā)的同步和打包機出包代碼的時效性
如何生成SNAPSHOT?
工程中已經(jīng)集成了nnaven_publish.gradle,在rootProject下執(zhí)行如下命令即可更新本地依賴的module到倉庫中:
./gradlew qpublish
該腳本需要結(jié)合component中的maven.properties文件:
# module的版本
MODULE_VERSION=1.0.6
# module的maven名
MODULE_ID=common
# 標記不生成SNAPSHOT
IS_LIB=true
其中IS_LIB是為了剔除common等lib声滥,IS_LIB標記后不會生成SNAPSHOT眉撵,標準的component工程不需要添加。
為了保證snapshot刷新的時效性落塑,工程配置了cacheChangingModulesFor刷新時間:
configurations.all{
resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
}
實時刷新可能會影響編譯速度纽疟,不需要的話可以在rootProject的properties中修改標志位:
# is refrsh snapshot
REFRESH_SNAPSHOT = false
正式環(huán)境
在提測接近結(jié)束時,需要將更新過的component進行發(fā)版憾赁。具體步驟如下:
1.版本需要指定版本號污朽,更新component下的maven.gradle文件:
# module的版本
MODULE_VERSION=1.0.0.1
# module的maven名
MODULE_ID=common
將MODULE_VERSION指定為最新版本,版本號的規(guī)則約定如下:
"${version_name}.x"
比如趣喝水初版版本為1.0.0龙考,對應的component版本號為:1.0.0.1到1.0.0.99蟆肆,期間可能還存在代碼修改的情況,因此預留兩位用于更新
2.提交代碼到遠程倉庫
將component的代碼更新到release/xxx上晦款,xxx為指定的flavor炎功,如release/drinkwater。
在QDepend中 component的release/xxx類似git flow中的master缓溅,可以添加權(quán)限蛇损,以及用于code review
3.ModuleToMaven上執(zhí)行打包命令
通過jenkins,選擇需要更新的component和flavor,然后build
4.更新工程的依賴
將項目中對component的依賴更新到固定版本:
implementation 'com.qtshe.mobile.component:drinkwater-login:1.0.0.1'
5.發(fā)版文檔更新
每個項目都有有自己的wiki文檔淤齐,開發(fā)負責人需要發(fā)版前進行更新