1. 程式人生 > >美團點評Android客戶端融合架構演進之路

美團點評Android客戶端融合架構演進之路

一 背景

點評美團合併之後,業務需要整合,我們部門的幾條業務需要往美團平臺遷移,為了降低遷移成本,開發和維護成本,以及將來可能要做的單元測試,需要對架構進行相應的調整。之前的程式碼都堆在Activity或Fragment裡面,UI,業務,資料混合在一起,就使得難以單獨的複用和擴充套件、測試。

二 目標

  • 程式碼複用

  • UI獨立

  • 業務獨立

  • 資料獨立

  • 可測試


公眾號:JANiubility

三 簡潔架構

這裡先引入簡潔架構的概念,該架構由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