【譯】更清晰的Android應(yīng)用架構(gòu)-MVP

原文鏈接Architecting Android…The clean way?

? ? ? 在過去的幾個(gè)月中我與公司Tuenti@pedro_g_s@flipper83(兩位android技術(shù)大牛)兩位同事討論Android應(yīng)用架構(gòu),我決定抽出一點(diǎn)時(shí)間寫一篇關(guān)于Android應(yīng)用架構(gòu)的文章。

? ? ? 通過我過去幾個(gè)月的學(xué)習(xí)和實(shí)踐總結(jié)了一些方法,它們將向你展示如何去實(shí)現(xiàn)這種清晰的Android架構(gòu)。

開始前的一些準(zhǔn)備

? ? ? 我們知道開發(fā)一個(gè)高質(zhì)量的軟件是非常困難和復(fù)雜的,它不僅是為了滿足功能實(shí)現(xiàn),也應(yīng)該是健壯、易維護(hù)、易測(cè)試和適于伸縮構(gòu)建。這就是“清晰架構(gòu)”的由來,這可能是開發(fā)任意軟件程序的最好方法。

? ? ? “清晰架構(gòu)”的概念很簡(jiǎn)單,產(chǎn)品系統(tǒng)中遵循一系列的習(xí)慣原則:

1、與框架分離

2、易測(cè)試

3、與UI分離

4、與數(shù)據(jù)庫分離

5、與其它外部組件分離


上圖中你所看見的不一定非要4個(gè)圓環(huán)來表示,因?yàn)檫@只是原理圖但你應(yīng)該考慮到相關(guān)規(guī)則

源碼依賴只能指向內(nèi)環(huán)而內(nèi)環(huán)不能知道它所在外環(huán)的任何事情。

下面的一些術(shù)語可以讓你明白和了解這是種非常好的架構(gòu)方式:

? ? ? 實(shí)體:他們是程序的業(yè)務(wù)對(duì)象

? ? ? 用例:他們是鏈接數(shù)據(jù)流和實(shí)體間的紐帶,也可叫作Interactor(翻譯成:交互器和耦合器,感覺都不對(duì))

? ? ? 接口適配器:這些適配器為用例和實(shí)體提供相應(yīng)格式的數(shù)據(jù)。Presenter(展現(xiàn)層)和Controller(控制層)都奴屬于這里。

? ? ? 框架和驅(qū)動(dòng):這里是所有的具體實(shí)現(xiàn),如:界面,工具類,框架等等

更加詳盡的解釋參見這篇文章The Clean Architecture和視頻Robert C. Martin - Clean Architecture?(貌似需要翻墻)

我們的方案

? ? ? 我們將從一個(gè)簡(jiǎn)單的案例開始:簡(jiǎn)單的創(chuàng)建一個(gè)app,這個(gè)app顯示一個(gè)從云端取回的朋友或用戶數(shù)據(jù),當(dāng)單擊列表中的任意一個(gè)條目時(shí),然后打開一個(gè)新的窗口顯示這個(gè)用戶的具體細(xì)節(jié)。

? ? ? 給你們看一個(gè)視頻,你們就知道我講的什么:Clean Architecture on Android - Sample App(需要翻墻)

Android架構(gòu)

? ? ? 遵循“關(guān)注分離”的原則來讓內(nèi)環(huán)的業(yè)務(wù)操作不知道外環(huán)的一切,不依賴任何外部元素所以他們易于測(cè)試。

? ? ? 要做到這一點(diǎn),“我的建議是將這個(gè)項(xiàng)目分離成3個(gè)不同的層”,這樣每個(gè)層只關(guān)心自己的目標(biāo)和工作以至獨(dú)立于其它層。

? ? ? 值得一提的是,每個(gè)層只使用它自己的數(shù)據(jù)模塊來達(dá)到獨(dú)立性(你將在代碼中見到那個(gè) data mapper被用來實(shí)現(xiàn)數(shù)據(jù)轉(zhuǎn)換,如果你不在整個(gè)應(yīng)用中跨模塊使用只需小的代價(jià))

這兒是一個(gè)我建議的三層模式:

注意:我沒有使用任何第三方庫(除了解析json數(shù)據(jù)的GSON、用于測(cè)試的junit,mockito、robolectri、espresso)這是為了使這個(gè)示例更加整潔。在你的開發(fā)中,無論如何不要猶豫去添加你所熟悉的存儲(chǔ)數(shù)據(jù)的ORMs框架、依賴注入框架、任何工具、第三方庫,這樣在編寫整個(gè)示例過程中可以省掉不少功夫(記?。褐貜?fù)造輪子不是個(gè)好習(xí)慣)。

展現(xiàn)層(Presentation Layer

? ? ? ?這兒是視圖和動(dòng)畫相關(guān)邏輯呈現(xiàn)的地方,它就是 Model View Presenter模式的一部分(參見:MVP),但你可以使用其它模式像MVC或MVVM。我不會(huì)進(jìn)一步闡述他們,但這里的Fragments 與Activities僅僅是一個(gè)Views,這里不會(huì)有邏輯存在于UI邏輯中,并且這里是視圖渲染填充的地方。這層中的Presenters結(jié)合interactors (用例)在UI線程之外的新線程中執(zhí)行任務(wù)隨后使用回調(diào)函數(shù)傳參的形式來渲染視圖。

如果你想要一個(gè)很酷的MVP和MVVM使用例子,你可以查看我朋友Pedro Gómez的Effective Android UI。

領(lǐng)域?qū)樱?b>Domain Layer

這里是業(yè)務(wù)規(guī)則:所有邏輯發(fā)生在這層. 對(duì)于Android 項(xiàng)目你也會(huì)在這里見到所有的interactors(用例)實(shí)現(xiàn)。

這層是一個(gè)純java模塊而不是其它Android依賴。所有外部組件使用接口連接業(yè)務(wù)對(duì)象

數(shù)據(jù)層(Data Layer

? ? ? 應(yīng)用需要的所有數(shù)據(jù)都來自這層,通過一個(gè)UserRepository實(shí)現(xiàn)(這個(gè)接口在領(lǐng)域?qū)樱?,它使用一個(gè)Repository Pattern和一個(gè)策略相結(jié)合,通過一個(gè)工廠,依賴某些條件來獲取不同的數(shù)據(jù)源。例如通過一個(gè)id來獲取用戶,隨后獲取該用戶在磁盤上的緩存數(shù)據(jù),如果該用戶存在的話,否則將從云端檢索數(shù)據(jù)隨后保存在磁盤緩存中。

? ? ? 這個(gè)背后的理念是所有數(shù)據(jù)對(duì)于客戶端來說都是透明的,它并不關(guān)心來自內(nèi)存、磁盤、還是云端的數(shù)據(jù)是怎樣傳遞和獲取的。

注意:我的代碼實(shí)現(xiàn)非常簡(jiǎn)單,使用文件系統(tǒng)和Android Preferences作為磁盤緩存,這是為了達(dá)到學(xué)習(xí)的目的。重申:如果已有第三方庫能勝任這種工作就不要重復(fù)的造輪子。

錯(cuò)誤處理(Error Handling)

? ? ? 這總是一個(gè)值得討論的話題,如果你有更好的解決方案請(qǐng)共享在這兒。

? ? ? 我的策略是使用回調(diào)接口, 以數(shù)據(jù)存儲(chǔ)響應(yīng)為例,回調(diào)接口中有onResponse()onError()兩個(gè)方法。這里封裝了一個(gè)叫“ErrorBundle”異常處理類:這種方法也帶來一些困難,因?yàn)檫@兒是一個(gè)回調(diào)鏈直接將錯(cuò)誤拋給展現(xiàn)層(Presentation Layer)。代碼可讀性不太好。

? ? ? 另外,我的主張是實(shí)現(xiàn)一個(gè)事件總線系統(tǒng)去拋事件當(dāng)某些錯(cuò)誤發(fā)生時(shí),但這類似使用GOTO。當(dāng)你訂閱幾個(gè)事件時(shí),如果你不善于控制處理它們,你會(huì)感到很困惑。

測(cè)試(Testing

? ? ? 對(duì)于測(cè)試,根據(jù)不同層我選擇了幾個(gè)不同的方案:

? ? ? 展現(xiàn)層(Presentation Layer):使用android instrumentation、espresso集成測(cè)試、功能性測(cè)試。

? ? ? 領(lǐng)域?qū)樱―omain Layer):使用JUnit+mockito(java模擬測(cè)試框架)進(jìn)行單元測(cè)試

? ? ? 數(shù)據(jù)層(Data Layer):Robolectric(因?yàn)檫@層有Android依賴)+junit+mockito進(jìn)行集成和單元測(cè)試

我的代碼(Show me the code

? ? ?我知道你在想我的代碼在哪里,沒錯(cuò)?這里是github鏈接代碼,在里邊你將知道我是怎么做的,關(guān)于項(xiàng)目結(jié)構(gòu)不得不提一句,使用模塊來區(qū)分不同的層:

? ? 展現(xiàn)層(presentation):它是一個(gè)Android module,它代表展現(xiàn)層。

? ? 領(lǐng)域?qū)樱╠omain):一個(gè)純java對(duì)象模塊而不是 Android Dependencies

? ? 數(shù)據(jù)層(data):一個(gè)Android Module,所有數(shù)據(jù)都從這里檢索

? ? data-test:為數(shù)據(jù)層提供測(cè)試,使用Robolectric時(shí)的某些局限性,不得不在一個(gè)單獨(dú)的java模塊中使用它

結(jié)論(Conclusion)

正如鮑勃叔說,“Architecture is About Intent, not Frameworks”,我完全同意這個(gè)說法當(dāng)然這兒有許多不同的做法(不同的實(shí)現(xiàn))我非常肯定,你和我一樣每天面臨很多挑戰(zhàn),但使用這些技術(shù),你開發(fā)的軟件將:

? ? ? 1、易于維護(hù)(Easy to maintain

? ? ? 2、易于測(cè)試(Easy to test

? ? ? 3、內(nèi)聚性強(qiáng)(Very cohesive

? ? ? 4、解耦(Decoupled

我強(qiáng)烈建議你嘗試并分享你的結(jié)果和體驗(yàn),也許你能找到其它工作得更好的方法:我們知道持續(xù)改進(jìn)是一件非常好的事。

我希望這篇文章能幫到你,非常歡迎并期待你的反饋!

源碼(Source code):

? ? ? ?1、Clean architecture github repository – master branch

? ? ? ?2、Clean architecture github repository –?releases

下載源碼的朋友注意咯:

? ? ? ? 請(qǐng)進(jìn)入第二個(gè)鏈接去下載:我下載的v0.5.0版,其它版本原作者在里邊使用了Dagger 2注解框架,如果你沒有使用過dagger 2, 當(dāng)你在看源碼的時(shí)候可能很茫然(比如說我)

? ? ? ? 我用UML的形式分析了下作者的這個(gè)源碼(v0.5.0版)并把圖上傳在這里:希望能幫助你快速閱讀?

下載地址

延伸閱讀(Further reading)

? ? ? ?1、Architecting Android..the evolution

? ? ? ?2、Tasting Dagger 2?on Android

? ? ? ?3、The Mayans Lost Guide to RxJava on Android

? ? ? ?4、It is about philosophy: Culture of a good programmer

鏈接和資源(Links and Resources

? ? ? 1、The clean architecture by Uncle Bob

? ? ? 2、Architecture is about Intent, not Frameworks

? ? ? 3、Model View Presenter

? ? ? 4、Repository Pattern by Martin Fowler

? ? ? 5、Android Design Patterns Presentation

最后編輯于
?著作權(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)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,056評(píng)論 25 709
  • afinalAfinal是一個(gè)android的ioc,orm框架 https://github.com/yangf...
    passiontim閱讀 15,876評(píng)論 2 45
  • 一種更清晰的Android架構(gòu) 原文鏈接 : Architecting Android…The clean way...
    mimimomo閱讀 728評(píng)論 0 10
  • 有了 Docker 搭建什么服務(wù)之類的簡(jiǎn)直不要太簡(jiǎn)單, metabase 分分鐘即可搭建完成。 安裝 ** 方法二...
    李方成閱讀 6,433評(píng)論 0 3
  • 簡(jiǎn)約不簡(jiǎn)單這種話,有錢人說說可以,什么叫簡(jiǎn)約,三百平米做客廳,三百平米做書房,三百平米滾床單,三百平米練瑜伽,三百...
    令狐大蔥閱讀 255評(píng)論 0 0

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