更多 Android 博文請關注我的博客 http://xuyushi.github.io
本文為翻譯,在原文的基礎上略有改動
http://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/
Getting Started
當你寫一個軟件時不僅要滿足需求,還要使得系統健壯、易于測試、方便修改。這樣才能滿足需求的變化。寫滿足這些條件的程序通常是很難很復雜的。這就是為什么提出 “the clean architecture”,這可能是在開發任何應用程序時都是一個不錯的辦法
理念很簡單。clean 架構 代表了一組擁有如下特點的實踐
- 框架獨立
- 容易測試
- UI獨立
- 數據庫獨立
-
不依賴任何中介
實際情況可能和上圖不一致,圖片只是示意,不是一定要分為4層,我們需要考慮的是依賴規則,依賴關系只能是外層依賴內層,內層不應該知道外層的存在
為了更方便的理解,下面是一些名詞解釋
- Entities: APP 的業務邏輯
- Use Cases:這些用例從
Entities
中流入流出,也被稱作Interactors
- Interface Adapters:這些 adapter 將data 轉換為方便 Use Cases使用的結構。Presenters 和 Controllers 都屬于這里
- Frameworks and Drivers: 所有 UI 細節、工具、框架
Our Scenario
...(作者例子的視頻展示)
Android Architecture
我們的目標是分離業務邏輯,使得業務邏輯對外部不感知。這樣我們在外部可以獨立對業務代碼進行測試
為了達成這個目標,我們的目的是將項目分為三層,每層都有自己的目的并且獨立于其它層
值得一提的是為了達到每層都獨立,每一層都有自己的數據結構。(在代碼可以看到通過 mapper來進行層與層之間的數據變換)
框架大致是這樣
NOTE: 我沒有使用任何的第三方庫(除了使用 gson 來解析數據,junit,mockito,robolectric 和 espresso 來測試),不使用第三庫的原因是我希望例子能更清晰。不用猶豫使用 ORMs做存儲,或者依賴注入框架,或者任何使你更方便的的工具(記住重復造輪子并不好)。
Presentation Layer
view 和動畫的邏輯的地方。使用了 MVP 模式(可以看這篇 http://xuyushi.github.io/2016/02/28/MVP/ ),你也可以使用 MVC,MVVM。我不會深入講解這部分。fragments、activities都只是 view,沒用業務邏輯, ,渲染的邏輯也在這
其中的Presenters是由** interactors (use cases)**組成的,這些 use cases 在 UI 線程之外的其他線程做一些工作,并且在回調中更新 view
Domain Layer
所有的業務邏輯都在這一層,對于 Android 工程,所有的interactors (use cases)的實現都在這一層。
這一層是純 java 的,沒用 android 的相關依賴,所有的外部交互都是通過接口實現的
Data Layer
所有應用需要的數據都通過這一層的UserRepository(domain 層定義接口的實現)獲取,這里使用了 Repository Pattern 模式,通過 factory 選取不同的 data 的數據源
舉個栗子,當我們需要獲取一個 userID,如果disk 緩存有則使用他,若沒有,則獲取數據,并把數據保存在 disk 緩存中
核心的思想是 data 的獲取對客戶端透明,客戶端無需關注數據的來源,內存,disk,或者網絡。客戶端只需要獲取數據
NOTE:同上個 NOTE,數據庫的實現比較簡單,可以使用第三方庫。 不要重復造輪子
Error Handling
這一直是一個值得討論的話題,我在這里分享一下我的解決方案。我的策略是使用回調,舉個栗子,如果在repository
產生事件之后,callback中包含兩個方法,onResponse()
和onError()
,后者把錯誤封裝在 ErrorBundle
類里:這樣帶來一個問題,因為錯誤通過層層傳遞導致代碼可讀性變差。
另一方面,我們可以實現一個 event bus 系統來拋出錯誤,這種解決方法類似于 GOTO 語句。在我的觀點中,當你訂閱了多個事件是你很容易弄混
Testing
對于測試,對于每層我都給出了不同的解決方案
- Presentation Layer: 使用
android instrumentatio
和espresso
做集成 和功能測試 - Domain Layer: 使用
JUnit
和mockito
做單元測試 - Data Layer: 使用
Robolectric
(因為這層有 Android 的依賴)和 junit、mockito做集成和單元測試。
Show me the code
https://github.com/android10/Android-CleanArchitecture
通過 module 來表示不同的層
- presentation: Android Module
- domain: 沒有 依賴Android的 java Module
- data: Android Module,獲取數據的地方
- data-test: Data 的測試。
Conclusion
就像Bob大叔所說的,『Architecture is About Intent, not Frameworks』。
確保的應用滿足以下幾點:
- 易維護 Easy to maintain
- 易測試 Easy to test.
- 高聚合Very cohesive.
- 低耦合 Decoupled.
**我現在根據這個架構為模板做一個開源 APP,完成以后會開源,詳見請見 http://xuyushi.github.io/tags/從零開始/ **