原文出處----->[架構Android ...干凈的方式?](https://fernandocejas.com/2014/09/03/architecting-android-the-clean-way/)(需要翻墻),作者[GitHub地址](https://github.com/android10/Android-CleanArchitecture)
### 譯文如下:
### 架構Android ...干凈的方式?
在過去的幾個月里,在[Tuenti](http://corporate.tuenti.com/en/dev/blog)和@[pedro_g_s](https://twitter.com/pedro_g_s)和[@ flipper83](https://twitter.com/flipper83)進行了幾次Android討論之后,我決定寫一篇關于**構建android應用程序**的文章。
其目的是在最近幾個月向您展示一些我想到的方法,以及從調查和實施中學到的所有東西。
#### 入門
**我們知道,編寫高質量的軟件很難,也很復雜**:既要滿足要求,又要有穩健性,可維護性,可測試性和靈活性,以適應增長和變化。這就是“**干凈的架構**”出現的地方,在開發任何軟件應用程序時可能是一個很好的方法。
這個想法很簡單:**干凈的建筑**代表了一組實踐,產生的系統是:
* **獨立于框架**。
* **可測試**。
* **獨立的用戶界面**。
* **獨立于數據庫**。
* **獨立于任何外部機構**。

不要只用4個圓圈(如圖所示),因為它們只是示意圖,但是應該考慮**依賴規則:源代碼依賴只能向內指向,內圈的任何東西都不能知道任何關于外圈的事情。**
以下是一些與熟悉和理解這種方法相關的詞匯:
* **信息**內讀范圍的信息信息中信息
* **使用案例**:這些使用案例協調實體之間的數據流。也被稱為交互者。
* **接口適配器**:這組適配器將轉換來自用例和實體最方便的格式的數據。演示者和控制者屬于這里。
* **框架和驅動程序**:這是所有細節去的地方:UI,工具,框架等
* 有關更好更廣泛的解釋,請參閱[本文](http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html)或[本視頻](http://vimeo.com/43612849)。
#### 我們的情景
**我將從一個簡單的場景開始**:簡單地創建一個小應用程序,顯示從云中檢索到的朋友或用戶列表,點擊其中的任何一個時,將打開一個新的屏幕,并顯示更多詳細信息為那個用戶。這是一個快速的視頻:
#### Android架構
目的是通過保持業務規則對外界不了解任何事情來**分離關注點**,從而可以在不依賴任何外部元素的情況下進行測試。
為了達到這個目的,**我的建議是把這個項目分成3個不同的層次**,每個**層次**都有自己的目的,分別工作。
**值得一提的是,每一層使用自己的數據模型,使這種獨立性可以達到**(你將在需要為了一個數據映射器來完成數據轉換,要付出的代價代碼中看到的,如果你不想穿越在整個應用程序中使用你的模型)。
**這是一個模式,所以你可以看到它是如何看起來像**:

**注意**:我沒有使用任何外部庫(gson除了解析json數據和junit,mockito,robolectric和espresso進行測試)。原因是**它使例子更清楚**。無論如何,不要猶豫,添加ORMs存儲磁盤數據或任何依賴注入框架或任何你熟悉的工具或庫,可以使您的生活更輕松。(請記住,**重新發明輪子不是一個好的做法**)。
#### 表示層
在這里,發生與視圖和動畫相關的邏輯。它只使用**模型視圖展示器**(MVP從現在開始),但您可以使用任何其他模式,如MVC或MVVM。我不會詳細介紹它,但是在這里,**片段(fragments )和活動(activities )只是視圖**,除了UI邏輯之外,他們內部沒有任何邏輯,這就是所有渲染的地方。
這個層中的**演示者Presenters**由**交互者用例**組成,他們在**主UI線程之外的一個新線程**中執行工作,然后使用一個回調來處理將在視圖中呈現的數據。
clean_architecture_mvp
如果您想要一個關于使用MVP和MVVM的[有效Android UI](https://github.com/pedrovgs/EffectiveAndroidUI/)的酷炫示例,請看看我的朋友PedroGómez做了什么。
**域圖層**
**這里的業務規則:所有的邏輯發生在這一層**。關于android項目,你也會在這里看到所有的交互器(用例)實現。
**這個層是一個沒有任何android依賴的純java模塊**。連接到業務對象時,所有外部組件都使用接口。

#### 數據層
**應用程序所需的所有數據都來自于此層,通過一個使用[Repository Pattern](http://martinfowler.com/eaaCatalog/repository.html)的UserRepository實現(接口位于域層),其策略通過工廠根據特定條件選擇不同的數據源。**
例如,當通過id獲取用戶時,如果用戶已經存在于緩存中,則將選擇磁盤緩存數據源,否則將查詢云以檢索數據并稍后將其保存到磁盤緩存中。
**所有這一切背后的思想是,數據來源對于客戶端來說是透明的**,不管數據來自內存,磁盤還是云,不管數據是來自內存,磁盤還是云,唯一的事實就是數據將會到達并被獲取。

**注意**:就代碼而言,我使用文件系統和Android偏好實現了一個非常簡單和原始的磁盤緩存,這是為了學習的目的。再次記住,如果現有的庫以更好的方式執行這些工作,**則不應該增加輪子**。
#### 錯誤處理
這總是一個討論的話題,如果你在這里分享你的解決方案,可能會很好。
**我的策略是使用回調**,因此,如果數據存儲庫中發生了一些情況,回調**函數**有兩個方法**onResponse**()和**onError**()。最后一個將異常封裝在名為“**ErrorBundle**”的包裝類中:這種方法帶來了一些困難,因為存在一**串接**一個的回調,直到錯誤進入表示層來呈現。代碼可讀性可能有點妥協。
另一方面,我可以實現一個事件總線系統,如果發生了錯誤,就會拋出事件,但是這種解決方案就像使用[GOTO一樣](http://www.drdobbs.com/jvm/programming-with-reason-why-is-goto-bad/228200966),而且**在我看來,當你訂閱了幾個事件時,有時你會迷路如果你不密切控制**。
#### 測試
關于測試,我根據圖層選擇了幾個解決方案:
* **表示層**:使用android儀器和espresso進行集成和功能測試。
* **域層**:在這里使用JUnit加單元測試的mockito。
* **數據層**: Robolectric(因為這層有android依賴),加上junit加mockito進行集成和單元測試。
#### 給我看代碼
**我知道你可能想知道代碼在哪里,對嗎?**那么這里是[github鏈接](https://github.com/android10/Android-CleanArchitecture),你會發現我所做的。關于文件夾結構,需要提到的是,不同的層使用模塊來表示:
* **演示文稿**:這是一個代表演示文稿層的android模塊。
* **域**:一個沒有android依賴關系的java模塊。
* **數據**:從中檢索所有數據的android模塊。
* **數據測試**:測試數據層。由于使用Robolectric時的一些限制,我不得不在獨立的java模塊中使用它。
#### 結論
正如Bob叔叔所說,“**架構是關于意圖,而不是框架**”,我完全同意這個說法。當然,有很多不同的方式來做事情(不同的實現),我很確定你(像我)每天面對很多挑戰,但是**通過使用這種技術**,你確保你的應用程序將:
* **易于維護**。
* **易于測試**。
* **非常有凝聚力**。
* **分離**。
**作為一個結論,我強烈建議你試一試,看看并分享你的結果和經驗**,以及你發現的更好的方法:我們知道**持續改進**總是一個非常好的和積極的東西。
我希望你已經發現這篇文章有用,并一如既往,任何反饋非常歡迎。
#### 源代碼
* [清潔架構github倉庫 - 主分支](https://github.com/android10/Android-CleanArchitecture)
* [清潔架構github存儲庫 - 發布](https://github.com/android10/Android-CleanArchitecture/releases)
#### 進一步閱讀:
* [構建Android ..的進化](http://fernandocejas.com/2015/07/18/architecting-android-the-evolution/)
* [在Android上品嘗Dagger 2](http://fernandocejas.com/2015/04/11/tasting-dagger-2-on-android/)
* [瑪雅人在Android上丟失了RxJava指南](https://speakerdeck.com/android10/the-mayans-lost-guide-to-rxjava-on-android)
* [這是關于哲學:一個好程序員的文化](https://speakerdeck.com/android10/it-is-about-philosophy-culture-of-a-good-programmer)
#### 鏈接和資源
* [由Bob叔叔干凈的架構](http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html)
* [架構是關于意圖,而不是框架](http://www.infoq.com/news/2013/07/architecture_intent_frameworks)
* [模型查看演示者](http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter)
* [版本庫模式由Martin Fowler提供](http://martinfowler.com/eaaCatalog/repository.html)
* [Android設計模式演示文稿](http://www.slideshare.net/PedroVicenteGmezSnch/)