起源
我們知道,軟件開發(fā)項目是一個綜合平衡的過程盖淡,要平衡時間、成本褪迟、范圍、質量四個要素味赃,在單個項目中掀抹,這四要素是非此即彼的:時間緊迫就要壓縮需求范圍心俗,添加需求就要追加成本傲武,確保質量就不能過于壓縮工期,相互之間無法調和城榛。
但如果跳出單個項目揪利,在日常積累上面下功夫狠持,我們卻有可能找到一種同時有利于項目四要素的途徑,就是建立和使用通用的開發(fā)架構甜刻。
大部分公司不會僅研發(fā)一個App,而是會研發(fā)一系列App尿招,形成家族化矾柜、品牌化就谜,或互相依賴丧荐,或入場試錯缆瓣,這些App功能業(yè)務可能不盡相同,但一般都需要網絡模塊/日志模塊/圖像加載模塊虹统,需要一些常見的簡單函數(shù)弓坞,為建立品牌形象,還需要統(tǒng)一的主題資源如色調/圖標/提示語等车荔。
這些低水平的重復開發(fā)渡冻,是與業(yè)務沒有直接關系卻必須支付的“死重”,是可以通過模塊復用來提升效率的忧便,這也是我們做Android架構分層的初衷族吻,我們把開發(fā)中常用的模塊抽象出來,分組分層珠增,形成結構清晰超歌,組裝靈活的通用組件庫,支撐起了多個App的快速實現(xiàn)與迭代蒂教。
價值
在實際開發(fā)過程中巍举,我們發(fā)現(xiàn)通用組件庫對于開發(fā)的效率和質量,都有了顯著的提升:
1.節(jié)省時間凝垛,因為組件功能可以復用禀综,能降低團隊成員熟悉項目的成本,為新業(yè)務開發(fā)提供基礎苔严,加快開發(fā)迭代速度定枷,有利于更快地發(fā)布版本。
2.降低成本届氢,把穩(wěn)定的公共模塊抽象為通用組件庫欠窒,提供給各個業(yè)務線協(xié)作使用,能在全公司范圍內減少重復開發(fā)和升級維護的工作量
3.提升質量,頻繁使用的功能/業(yè)務模塊采用組件復用方式岖妄,更有利于暴露缺陷型将,一處修改,多處受益荐虐,提高產品質量七兜。
具體設計
對于App來說,選用組件應該按需取用福扬,僅選用自己需要的那些組件腕铸,這就需要把組件分離為多個,形成一個結構化的組件庫铛碑,我們最終形成的組件庫大概是這樣的:
在上圖的結構中狠裹,通用組件是與業(yè)務無關的基礎功能,共享組件是與業(yè)務有緊密聯(lián)系的汽烦,共享組件可能需要引用通用組件涛菠。
在具體實現(xiàn)中,我們處理過這樣幾個問題:
- 引用形式
在引用形式上撇吞,我們有aar和module代碼兩種方式俗冻,其中aar適合函數(shù)已經固定,不允許擴展修改的情況牍颈;module適合類型已經分開言疗,但是函數(shù)并未固定,可以增加新函數(shù)的情況颂砸。 - 依賴倒置
在引用第三方庫時,我們禁止直接引用死姚,App可以直接引用第三方庫人乓,但是組件必須使用自己的接口,這樣在第三方庫升級或者更換時都毒,不會影響頂層的app色罚。
例如網絡層必須使用網絡組件自己定義的callback接口,實際上就是都要依賴于抽象账劲,不能依賴具體戳护。 - 接口隔離
組件庫大量使用接口為App服務,這要求接口保持互相隔離瀑焦,盡量把功能拆分到多個接口里腌且,不能出現(xiàn)大而全的接口。 - 單一職責
每個組件僅負責一類功能榛瓮,互相之間可以有調用铺董,但不能出現(xiàn)一個大而全的組件。 - 開放封閉
組件中的函數(shù)是嚴禁修改的禀晓,可以增加新函數(shù)精续,但嚴禁修改已有函數(shù)坝锰,除非是為了消除缺陷。 - 異常拋出
底層組件有時候必須做異常捕獲重付,無論是Exception還是Error都需要拋出顷级,也就是說所有的Throwable都需要向上層拋出,避免應用層莫名其妙的發(fā)現(xiàn)流程被打斷确垫,無法查知底層組件出現(xiàn)的異常弓颈。 - 質量控制
底層組件的場景比較抽象也比較固定,實際上容易做單元測試和自動化測試森爽,為組件開發(fā)專門的自動測試模塊恨豁,甚至出一個自動測試demo,都是性價比很高的投入爬迟。 - 代碼追溯
對于module形式共享的組件橘蜜,實際上允許開發(fā)團隊進行擴展和修改,但是所有的變更都隱藏著缺陷付呕,所以在組件庫的代碼提交中计福,必須進行代碼審查,并注釋代碼修改的時間徽职、事由象颖、操作人等,以便在出現(xiàn)缺陷時進行追溯 姆钉。 - jar包沖突
長期維護下來说订,必然可能引用多個版本的第三方庫,這就會產生jar包沖突的問題潮瓶,所以有必要在底層建立一個整合第三方庫的module陶冷,各App共同引用這個庫module。 - 版本分支
有些情況下毯辅,某些第三方庫發(fā)生了大版本的迭代更新埂伦,更新前后的功能變化極大,導致app無法完美兼容思恐,這就需要建立版本分支沾谜,使用特定版本的組件庫,維持app的研發(fā)需求胀莹,直至app重構基跑,或app消亡。 - 路由解耦
有些業(yè)務組件是有Activity的描焰,這些組件之間跳轉時涩僻,為了解耦合,應該避免通過包名和類名去跳轉,可以參考Android的Intent思想逆日,允許通過action和category一起過濾嵌巷,找到跳轉目標,實際開發(fā)中可以做一個Router室抽,例如阿里開源的ARouter
最終搪哪,App選用組件庫的結構,大概是這樣的: