🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
原文出处----->[架构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应用程序**的文章。 其目的是在最近几个月向您展示一些我想到的方法,以及从调查和实施中学到的所有东西。 #### 入门 **我们知道,编写高质量的软件很难,也很复杂**:既要满足要求,又要有稳健性,可维护性,可测试性和灵活性,以适应增长和变化。这就是“**干净的架构**”出现的地方,在开发任何软件应用程序时可能是一个很好的方法。 这个想法很简单:**干净的建筑**代表了一组实践,产生的系统是: * **独立于框架**。 * **可测试**。 * **独立的用户界面**。 * **独立于数据库**。 * **独立于任何外部机构**。 ![clean_architecture1](https://box.kancloud.cn/76d2f5d0ea3a81429953a184b7ce457b_647x440.png) 不要只用4个圆圈(如图所示),因为它们只是示意图,但是应该考虑**依赖规则:源代码依赖只能向内指向,内圈的任何东西都不能知道任何关于外圈的事情。** 以下是一些与熟悉和理解这种方法相关的词汇: * **信息**内读范围的信息信息中信息 * **使用案例**:这些使用案例协调实体之间的数据流。也被称为交互者。 * **接口适配器**:这组适配器将转换来自用例和实体最方便的格式的数据。演示者和控制者属于这里。 * **框架和驱动程序**:这是所有细节去的地方:UI,工具,框架等 * 有关更好更广泛的解释,请参阅[本文](http://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html)或[本视频](http://vimeo.com/43612849)。 #### 我们的情景 **我将从一个简单的场景开始**:简单地创建一个小应用程序,显示从云中检索到的朋友或用户列表,点击其中的任何一个时,将打开一个新的屏幕,并显示更多详细信息为那个用户。这是一个快速的视频: #### Android架构 目的是通过保持业务规则对外界不了解任何事情来**分离关注点**,从而可以在不依赖任何外部元素的情况下进行测试。 为了达到这个目的,**我的建议是把这个项目分成3个不同的层次**,每个**层次**都有自己的目的,分别工作。 **值得一提的是,每一层使用自己的数据模型,使这种独立性可以达到**(你将在需要为了一个数据映射器来完成数据转换,要付出的代价代码中看到的,如果你不想穿越在整个应用程序中使用你的模型)。 **这是一个模式,所以你可以看到它是如何看起来像**: ![clean_architecture_android](https://box.kancloud.cn/0e8078d49f0965c7a45ef844fe7321b2_673x292.png) **注意**:我没有使用任何外部库(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模块**。连接到业务对象时,所有外部组件都使用接口。 ![clean_architecture_domain](https://box.kancloud.cn/5a16e4f5132205c58563d09a1e686e45_297x280.png) #### 数据层 **应用程序所需的所有数据都来自于此层,通过一个使用[Repository Pattern](http://martinfowler.com/eaaCatalog/repository.html)的UserRepository实现(接口位于域层),其策略通过工厂根据特定条件选择不同的数据源。** 例如,当通过id获取用户时,如果用户已经存在于缓存中,则将选择磁盘缓存数据源,否则将查询云以检索数据并稍后将其保存到磁盘缓存中。 **所有这一切背后的思想是,数据来源对于客户端来说是透明的**,不管数据来自内存,磁盘还是云,不管数据是来自内存,磁盘还是云,唯一的事实就是数据将会到达并被获取。 ![clean_architecture_data](https://box.kancloud.cn/bb5dff59a0db45e886df41279f80a24e_698x385.png) **注意**:就代码而言,我使用文件系统和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/)