整潔性架構
眾所周知,編寫高質量的代碼是困難且復雜的,在滿足需求的前提下,還要兼具健壯性、可維護性、可測試性和靈活性,以在代碼量的增長和需求變化時應付自如。
整潔性架構方案的提出,使得在開發任何軟件應用時可能都是的一個很好的架構方案。
整潔性架構方案其實很簡單,主要關注下面幾個點:
- 獨立于框架(無論是系統還是語言):該體系結構不依賴于一些特征負載軟件庫的存在。這允許您使用這樣的框架作為工具,而不是將系統壓縮到有限的約束。
- 可測試性(代碼可測性良好):可以在沒有UI,數據庫,Web服務器或任何其他外部元素的情況下測試業務規則。
- 獨立于UI:UI可以輕松改變,而不改變系統的其余部分。Web UI可以用控制臺UI替代,例如,不改變業務規則。
- 獨立于數據庫:您可以將Oracle或SQL Server,Mongo,BigTable,CouchDB或其他內容進行交換。您的業務規則未綁定到數據庫。
- 獨立于任何外部媒介:事實上,你的業務規則根本就不了解外界的任何事情。
如圖所示,這個圖應該關注的時依賴規則:源碼的依賴關系只能指向內部,內環的任何內容都不知道任何外部的內容。
分層來介紹圖中的角色
- Entities(實體):這些是應用程序的業務對象。
- Use Cases(用例):這些用例用于協調來自實體的數據流。也被稱為交互器。
- Interface Adapters(接口適配器):這套適配器以用例和實體最方便的格式轉換數據(這套的適配器為用例和實體轉換數據,轉換成最方便用例和實體使用的格式。)
- Frameworks and Drivers(框架和驅動程序):這里指所有的細節:UI、工具和框架等。
適用Android的整潔性架構
我們的目的是通過保持業務規則不知道外部世界的任何內容來分離關注點,這樣才能在不依賴于任何外部內容的前提下實現可測性。
為了達到這個目的,我們的建議是把項目劃分為三個不同的層次,每一層次都有自己的目的并且與其他的層次分開工作。
值得一提的時,每個層都是用自己的數據模型,因此可以達到這種獨立性(你會在示例項目中看到旨在完成數據轉換的數據映射器-Data Mapper,這是不必跨越整個應用去調用模型而保持獨立性必須付出的代價)。
這個方案看起來是下面這樣的:
Presentation Layer(展現層)
展現層是視圖和動畫相關邏輯發生的地方。該層中不但可以使用Model-View-Presenter模式(目前使用的MVP模式),也可以使用如MVC或者MVVM的其他模式。這里不詳細的介紹,只需要知道fragments和activities僅僅作為View(視圖),這里只有UI(用戶交互)的邏輯,是所有渲染工作發生的地方。
此層的Presenters由在工作線程執行任務的交互器(用例)組成, 并返回響應數據交給View去渲染頁面。
Domain Layer(領域層)
這里的業務規則:所有的邏輯都發生在這一層。對于安卓項目在這一層你能看到所有的交互器(用例)實現類。
此層是沒有依賴任何安卓依賴關系的純Java模塊。所有外部組件當需要和業務對象進行交互時,都使用接口建立鏈接。如下圖:
Data Layer(數據層)
應用程序所需的所有數據均來自此層,通過UserRepository(該接口在領域層中)實現類完成,該實現類采用庫模式策略來實現根據特定條件通過工廠選擇不同數據源。
例如,當需要通過ID獲取一個用戶的時候,如果這個用戶存在于緩存中,這時磁盤緩存數據源就會被選擇;否則的話,將會通過查詢云以獲取數據,然后后會將得到的結果保存到磁盤緩存中。
所有這一切的背后想法是,對于客戶端的數據源是透明的,client不關心數據是從內存磁盤還是云端,唯一的事實是數據可達并且獲取到了。
注意:示例代碼使用文件系統和Android preferences文件實現了一個非常簡單和原始的磁盤緩存,這是為了學習目的。請記住,如果有現有的開源庫以更好的方式執行這些工作,您不應該重復造輪子。
可測性
關于測試,我根據層選擇了幾種解決方案:
- 展示層:使用Android instrumentation和espresso進行集成和功能測試。
- 領域層: JUnit + mockito用于單元測試。
- 數據層: Robolectric(因為這個層有android依賴)加上junit + mockito進行集成和單元測試。
架構響應路徑
如下圖:
結論
正如Bob大叔所說,"架構關乎意圖而非框架"(Architecture is About Intent, not Frameworks),我完全同意這個說法。當然也有很多不同的做法(不同的實現方式),我很確定你同我一樣每天面臨很多挑戰,但是通過使用這種技術,可以確保你的應用程序:
- 容易維護
- 容易測試
- 高內聚
- 低耦合
以上,謝謝大家!