Android架構(gòu)分層演進(jìn)實(shí)踐

我們知道,軟件開(kāi)發(fā)項(xiàng)目是一個(gè)綜合平衡的過(guò)程,要平衡時(shí)間、成本、范圍、質(zhì)量四個(gè)要素,在單個(gè)項(xiàng)目中,這四要素是非此即彼的:時(shí)間緊迫就要壓縮需求范圍,添加需求就要追加成本,確保質(zhì)量就不能過(guò)于壓縮工期,相互之間無(wú)法調(diào)和。

但如果跳出單個(gè)項(xiàng)目,在日常積累上面下功夫,我們卻有可能找到一種同時(shí)有利于項(xiàng)目四要素的途徑,就是建立和使用通用的開(kāi)發(fā)架構(gòu)。

大部分公司不會(huì)僅研發(fā)一個(gè)App,而是會(huì)研發(fā)一系列App,形成家族化、品牌化,或互相依賴,或入場(chǎng)試錯(cuò),這些App功能業(yè)務(wù)可能不盡相同,但一般都需要網(wǎng)絡(luò)模塊/日志模塊/圖像加載模塊,需要一些常見(jiàn)的簡(jiǎn)單函數(shù),為建立品牌形象,還需要統(tǒng)一的主題資源如色調(diào)/圖標(biāo)/提示語(yǔ)等。

這些低水平的重復(fù)開(kāi)發(fā),是與業(yè)務(wù)沒(méi)有直接關(guān)系卻必須支付的“死重”,是可以通過(guò)模塊復(fù)用來(lái)提升效率的,這也是我們做Android架構(gòu)分層的初衷,我們把開(kāi)發(fā)中常用的模塊抽象出來(lái),分組分層,形成結(jié)構(gòu)清晰,組裝靈活的通用組件庫(kù),支撐起了多個(gè)App的快速實(shí)現(xiàn)與迭代。

image

image

價(jià)值

在實(shí)際開(kāi)發(fā)過(guò)程中,我們發(fā)現(xiàn)通用組件庫(kù)對(duì)于開(kāi)發(fā)的效率和質(zhì)量,都有了顯著的提升:

節(jié)省時(shí)間,因?yàn)榻M件功能可以復(fù)用,能降低團(tuán)隊(duì)成員熟悉項(xiàng)目的成本,為新業(yè)務(wù)開(kāi)發(fā)提供基礎(chǔ),加快開(kāi)發(fā)迭代速度,有利于更快地發(fā)布版本。

降低成本,把穩(wěn)定的公共模塊抽象為通用組件庫(kù),提供給各個(gè)業(yè)務(wù)線協(xié)作使用,能在全公司范圍內(nèi)減少重復(fù)開(kāi)發(fā)和升級(jí)維護(hù)的工作量

提升質(zhì)量,頻繁使用的功能/業(yè)務(wù)模塊采用組件復(fù)用方式,更有利于暴露缺陷,一處修改,多處受益,提高產(chǎn)品質(zhì)量。

image

具體設(shè)計(jì)

對(duì)于App來(lái)說(shuō),選用組件應(yīng)該按需取用,僅選用自己需要的那些組件,這就需要把組件分離為多個(gè),形成一個(gè)結(jié)構(gòu)化的組件庫(kù),我們最終形成的組件庫(kù)大概是這樣的:

image

在上圖的結(jié)構(gòu)中,通用組件是與業(yè)務(wù)無(wú)關(guān)的基礎(chǔ)功能,共享組件是與業(yè)務(wù)有緊密聯(lián)系的,共享組件可能需要引用通用組件。

image

在具體實(shí)現(xiàn)中,我們處理過(guò)這樣幾個(gè)問(wèn)題:

引用形式:在引用形式上,我們有aar和module代碼兩種方式,其中aar適合函數(shù)已經(jīng)固定,不允許擴(kuò)展修改的情況;module適合類型已經(jīng)分開(kāi),但是函數(shù)并未固定,可以增加新函數(shù)的情況。

依賴倒置:在引用第三方庫(kù)時(shí),我們禁止直接引用,App可以直接引用第三方庫(kù),但是組件必須使用自己的接口,這樣在第三方庫(kù)升級(jí)或者更換時(shí),不會(huì)影響頂層的app。例如網(wǎng)絡(luò)層必須使用網(wǎng)絡(luò)組件自己定義的callback接口,實(shí)際上就是都要依賴于抽象,不能依賴具體。

接口隔離:組件庫(kù)大量使用接口為App服務(wù),這要求接口保持互相隔離,盡量把功能拆分到多個(gè)接口里,不能出現(xiàn)大而全的接口。

單一職責(zé):每個(gè)組件僅負(fù)責(zé)一類功能,互相之間可以有調(diào)用,但不能出現(xiàn)一個(gè)大而全的組件。

開(kāi)放封閉:組件中的函數(shù)是嚴(yán)禁修改的,可以增加新函數(shù),但嚴(yán)禁修改已有函數(shù),除非是為了消除缺陷。

異常拋出:底層組件有時(shí)候必須做異常捕獲,無(wú)論是Exception還是Error都需要拋出,也就是說(shuō)所有的Throwable都需要向上層拋出,避免應(yīng)用層莫名其妙的發(fā)現(xiàn)流程被打斷,無(wú)法查知底層組件出現(xiàn)的異常。

質(zhì)量控制:底層組件的場(chǎng)景比較抽象也比較固定,實(shí)際上容易做單元測(cè)試和自動(dòng)化測(cè)試,為組件開(kāi)發(fā)專門的自動(dòng)測(cè)試模塊,甚至出一個(gè)自動(dòng)測(cè)試demo,都是性價(jià)比很高的投入。

代碼追溯:對(duì)于module形式共享的組件,實(shí)際上允許開(kāi)發(fā)團(tuán)隊(duì)進(jìn)行擴(kuò)展和修改,但是所有的變更都隱藏著缺陷,所以在組件庫(kù)的代碼提交中,必須進(jìn)行代碼審查,并注釋代碼修改的時(shí)間、事由、操作人等,以便在出現(xiàn)缺陷時(shí)進(jìn)行追溯 。

jar包沖突:長(zhǎng)期維護(hù)下來(lái),必然可能引用多個(gè)版本的第三方庫(kù),這就會(huì)產(chǎn)生jar包沖突的問(wèn)題,所以有必要在底層建立一個(gè)整合第三方庫(kù)的module,各App共同引用這個(gè)庫(kù)module。

版本分支:有些情況下,某些第三方庫(kù)發(fā)生了大版本的迭代更新,更新前后的功能變化極大,導(dǎo)致app無(wú)法完美兼容,這就需要建立版本分支,使用特定版本的組件庫(kù),維持app的研發(fā)需求,直至app重構(gòu),或app消亡。

路由解耦:有些業(yè)務(wù)組件是有Activity的,這些組件之間跳轉(zhuǎn)時(shí),為了解耦合,應(yīng)該避免通過(guò)包名和類名去跳轉(zhuǎn),可以參考Android的Intent思想,允許通過(guò)action和category一起過(guò)濾,找到跳轉(zhuǎn)目標(biāo),實(shí)際開(kāi)發(fā)中可以做一個(gè)Router,例如阿里開(kāi)源的ARouter

image

最終,App選用組件庫(kù)的結(jié)構(gòu),大概是這樣的:

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

相關(guān)閱讀更多精彩內(nèi)容

  • 起源 我們知道,軟件開(kāi)發(fā)項(xiàng)目是一個(gè)綜合平衡的過(guò)程,要平衡時(shí)間、成本、范圍、質(zhì)量四個(gè)要素,在單個(gè)項(xiàng)目中,這四要素是非...
    藍(lán)灰_q閱讀 1,691評(píng)論 0 3
  • 作者介紹馮宇飛 ,現(xiàn)任人人車Android客戶端架構(gòu)師。 本文回顧總結(jié)了人人車公司Android客戶端的架構(gòu)演進(jìn)歷...
    passiontim閱讀 1,641評(píng)論 0 9
  • Android組件化項(xiàng)目地址:Android組件化項(xiàng)目AndroidModulePattern Android組件...
    半灬邊灬天閱讀 2,996評(píng)論 4 37
  • 本文系總結(jié)作業(yè),部分參考內(nèi)容在這里 在 JavaScript 規(guī)范中,共定義了6+1,七種數(shù)據(jù)類型,分為6種原始類...
    竹鼠不要中暑閱讀 372評(píng)論 0 0
  • 很奇怪,在資本市場(chǎng)中經(jīng)常有人在教導(dǎo)別人要理性。而所有理性模式后面,都毫無(wú)例外地對(duì) 應(yīng)著一套價(jià)值系統(tǒng)為依據(jù),企圖通過(guò)...
    lexluseyan閱讀 598評(píng)論 0 1

友情鏈接更多精彩內(nèi)容