美團點評Android客戶端融合架構演進之路
一 背景
點評美團合併之後,業務需要整合,我們部門的幾條業務需要往美團平臺遷移,為了降低遷移成本,開發和維護成本,以及將來可能要做的單元測試,需要對架構進行相應的調整。之前的程式碼都堆在Activity或Fragment裡面,UI,業務,資料混合在一起,就使得難以單獨的複用和擴充套件、測試。
二 目標
-
程式碼複用
-
UI獨立
-
業務獨立
-
資料獨立
-
可測試
三 簡潔架構
這裡先引入簡潔架構的概念,該架構由Uncle Bob提出,他認為一個架構應該具有以下特性
-
框架獨立性
架構不應該依賴於現有的library,這樣可以讓你像工具一樣去使用架構,而不是對你的系統新增約束
-
可測試
業務邏輯可以在不依賴UI,資料庫,網路服務等其它外部因素的情況下進行測試
-
UI獨立性
在不變動系統其它部分的情況下,可以很方便的改變UI,比如,在沒有變動任何業務邏輯的情況下web ui可以被替換成console ui
-
資料庫獨立性
可以很自如的在Oracle,SQL Server之間切換,而不涉及業務邏輯
-
任何外部代理模組的獨立性
業務邏輯應該不需要知道外部世界的任何事情
下圖闡述了一個簡潔架構的各個層之間的關係
-
內層不應該知道外層的任何情況
-
各層之間通過介面互動
-
上層依賴下層,但依賴於介面
應用中最重部分就是業務邏輯層。它負責解決應用所真正想解決的問題。該層不包含任何框架相關的程式碼,因此其程式碼應該可以在沒有模擬器的情況下獨立執行。這樣,測試、開發和維護業務邏輯程式碼就要容易很多。而這就是乾淨架構的主要優勢。
下面簡單對以上幾個概念進行簡單的介紹
Entities
資料部分,一個Entity可以是一個帶有方法的物件,或者一個數據結構和方法的集合
Use Cases
該層包含了應用特定的業務規則,封裝了應用中所有的use cases。這些use cases從entities組裝資料流,傳遞給業務使用。
該層的變更不應該影響到Entities,也不希望該層會被database,UI,或者其它通用框架的外部變化所影響到,該層應該獨立於這些部分。
Interface Adapters
該層是一些為了便於use cases和entities的資料轉換的介面卡。這一層包含GUI的MVC架構,展示層,Views和Controllers都屬於該層。models更傾向於在controllers和use cases之間傳遞的資料結構,然後從use cases傳遞給Presenter和Views。
上面的這些原則足以構建高內聚,低耦合,可擴充套件的應用
四 Android架構探索
一個應用基本可以劃分為3個部分,UI,業務,和資料,而在移動端來說,更注重UI的展示,複雜的業務通常放在服務端。
針對這3部分,如何進行設計呢?
可以參考上面的基本原則 ,把整個專案拆分成3個不同的層級:
資料層— 業務層 — 展示層
每一層保持功能獨立,上層依賴下層,但依賴於介面,而不是具體。每一層擁有自己的資料模型,做到依賴獨立。
4.1 表現層(Presentation Layer)
常見的模式有MVP,MVC,MVVM
表現層除了UI相關邏輯,不應該含有任何邏輯,這一層應該很輕,資料的獲取和業務處理應該交給業務層和資料層,Presenter在該層由Use Cases組裝,Use Cases會在新的執行緒執行一個任務並使用一個帶有資料的回撥用於渲染view,下圖是MVP架構模組之間的基本關係
4.2 業務層 (Business logic(Domain) Layer)
業務層可能有些模糊,哪些應該屬於該層呢?
按照MVP的方式劃分,很容易理解的是,所有的業務邏輯放到P中即可。但實際開發中,你會發現,稍微複雜的業務,P層的程式碼就會變得非常臃腫。我認為P的角色作為業務邏輯的組裝更合適。業務邏輯可以進行相應的封裝,比如
另外業務層應該是純java程式碼,對android平臺沒有任何依賴,業務層向外暴露介面。
4.3 資料層(Data Layer)
資料層提供了資料來源,資料層也可以包括一些簡單的資料處理,比如JSON的封裝,一些model的轉換,外部不關心具體如何獲取資料的細節,只向資料層拿資料。比如下面展示了 倉庫模式(Repository Pattern)來實現資料層,它的策略是採用工廠模式,傳遞不同的條件引數,獲取不同的資料。
4.4 測試 (Testing)
基於上面的架構,我們更容易進行測試,不同的分層之間完全獨立,每一層也有自己相應的測試方案:
-
Presentation Layer: 使用Android自帶的
instrumentation
和espresso
做整合和功能測試。 -
Domain Layer:
JUnit
+mockito
做單元測試。 -
Data Layer:
Robolectric
(這一層開始有Android相關的依賴)+junit
+mockito
做單元和整合測試
五 表現層架構
MVC
Model–View–Controller (MVC) is a software architectural pattern for implementing user interfaces.*
MVP,MVC,MVVM 都是表現層的一種模式
這些架構相對於傳統的開發方式,門檻高些,要想深入掌握和更高層次的理解各個層的職責,需要一定積累,對於一些簡單的場景並不是一種好的方案,複雜的業務場景則會從中得到很多好處。
這些模式的好處
-
關注點分離,職責明確
o UI – 負責UI的渲染
o Presenter/controller – 負責響應UI事件並和Model互動
o Model – 負責業務行為和狀態管理
-
程式碼重用性
關注點和責任分離之後,各層獨立,可以增加程式碼的可用性
-
測試驅動
易於測試,只要寫一個實現了ViewInterface的類即可測試,而不需依賴android平臺
-
隱藏資料訪問
使用這種模式之後,資料的訪問程式碼就被劃分到data層
-
擴充套件性高,可適配
將程式碼分離到Presenter,Controller和Model中,可以更自由的適配
5.1 MVP
這裡簡單的介紹下MVP的基本元素
-
M:資料實體,封裝資料
-
V:檢視的渲染,事件的響應
-
P:中間層,作為與M和V通訊的橋樑,組裝業務邏輯
在MVP模式裡通常包含4個要素
(1) View: 負責繪製UI元素、與使用者進行互動(Activity或Fragment);
(2) View interface: View需要實現的介面,View通過View interface與Presenter進行互動
(3) Model: 業務Bean
(4) Presenter: 作為View與Model互動的紐帶,承載了大部分的複雜邏輯
5.2 MVP vs MVC
相同點
-
分離了不同元件之間的責任,降低了View和Model之間的耦合
不同點
-
MVP中,View與model之間的耦合更低,不容許View直接訪問Model,通過Presenter來互動,更加容易進行單元測試,因為View是通過介面來互動
-
通常View與Presenter的關係是一對一,複雜的View可能有多個Presenter
-
MVC可以決定展示哪個View,Controller依賴於行為,而且可以被多個View共用
5.3 MVP vs MVVM
MVP單項繫結,而MVVM採用雙向繫結(data-binding),View的變動,自動反映在 ViewModel,Model的變動也會反映到View中
其實MVP中Model是很輕的,資料的獲取和處理屬於架構中的資料層和業務層,所以這一點並不是很讓人能夠理解。
本篇文章主要是對android架構的探索,目前我們採用的是data+domain+MVP這種架構模式。
後期會分享在架構調整中所遇到的問題和經驗。
專案
參考文件
關於Java和Android大牛頻道
Java和Android大牛頻道是一個數萬人關注的探討Java和Android開發的公眾號,分享和原創最有價值的乾貨文章,讓你成為這方面的大牛!
我們探討android和Java開發最前沿的技術:android效能優化 ,外掛化,跨平臺,動態化,加固和反破解等,也討論設計模式/軟體架構等。由一群來自BAT的工程師組成的團隊。
關注即送紅包,回覆:“百度” 、“阿里”、“騰訊” 有驚喜!!!關注後可用入微信群。群裡都是來自百度阿里騰訊的大牛。
歡迎關注我們,一起討論技術,掃描和長按下方的二維碼可快速關注我們。或搜尋微信公眾號:JANiubility。
公眾號:JANiubility