【译】Android架构之引入clean 架构

原文链接:Architecting Android…The clean way?

在过去的几个月里,在Tuenti和同事@pedro_g_s和@flipper83(顺带一提,这两个都是Android开发高手)探讨之后,我觉得是时候写一篇关于构建Android应用架构方面的文章了。

本文的目的在于告诉你我过去几个月脑中的一些想法,还有我研究和实现后总结的一些资料。

Getting Started

我们知道编写高质量的软件很困难也很复杂:它不仅仅是符合需求,还要有鲁棒性、可维护、可测试和足够灵活,以适应代码增长和改变的需要。因此,我们提出了“the clean architecture“(清爽架构)的概念,它对于开发任何软件应用都是一个绝佳的方案。

这个概念很简单:clean architecture主张通过一系列的实践,来构建一个具备下面特性的系统:

  • Independent of Frameworks(框架独立)
  • Testable(可测试)
  • Independent of UI(用户界面独立)
  • Independent of Database(数据库独立)
  • Independent of any external agency(所有外部代理独立)
【译】Android架构之引入clean 架构_第1张图片

这并不是说一定只用这4层(如图所示),因为这张原理图只是要让你考虑Dependency Rule(依赖规则):源代码中的依赖只能指向里面,内圈代码必须对外圈的一无所知。

下面有一些相关的词汇能让你更好地熟悉和理解该方法:

  • Entities:应用的业务对象所在
  • Use Cases:协调数据从entities中流进流出。也可以叫Interactors。(备注:用例,就是一系列的步骤,典型地说就是用户为达到一种目的,与系统进行的交互)
  • Interface Adapters:转换数据以方便use cases和entities使用。Presenters和Controllers都属于此处
  • Frameworks and Drivers:细节处理,比如UI、tools、frameworks等等

更多更棒的解析,参见这篇文章和这个视频。

Our Scenario

我会从一个简单的方案开始讲起:一个简单的app,显示一个朋友或用户列表,数据从云端获取;当点击任意一项,会打开一个新界面,显示用户详情。

我录制了一个视频,这样你就可以对我谈论的东西有个大概了。

Android Architecture

我们的目标是:通过让业务逻辑对外部世界一无所获来进行解耦,这样,业务逻辑就可以毫无依赖地使用外部元素进行测试了。为了达到该目的,我的解决方案是划分项目成3个不同的层次,每个层都有各自的功能,并且各自独立工作。

值得一提的是,每个层使用各自的数据模型(data model),因为这种独立是可达的(你可以在代码中有一个data mapper,它用来完成数据的转换,如果你不想在整个应用中交叉使用models的话是要支付一定的代价的)

看看下面的图就知道了:

【译】Android架构之引入clean 架构_第2张图片
clean_architecture_android

注意:我没有使用任何外部类库(除了使用gson来解析json数据,使用junit、mockito、robolectric和espresso来测试)。这是为了让示例代码更清晰点。不管如何,你可以毫不犹豫地添加ORM进行数据存储或者任何依赖注入框架或者任何你熟悉的工具和类库,那样你的生活很更美好。(记住,不要重新造轮子)

Presentation Layer

这里放置的是关联视图和动画相关的逻辑代码。它不仅仅可以使用MVP模式(Model View Presenter),也可以使用MVC或MVVM。关于这点我不会展开来说。在这里,fragments和activities都只是views,里面没有任何逻辑,当然除了UI逻辑。所有需要渲染或展示的东西都在这里进行。

本层的Presentersinteractors(use cases)构成,在UI线程之外的新线程进行工作,然后通过回调将数据提供给view进行渲染或展示。

【译】Android架构之引入clean 架构_第3张图片
clean_architecture_mvp

如果你在找一个使用MVP和MVVM的酷酷的案例,推荐看看我朋友 Pedro Gómez 写的

Effective Android UI。

Domain Layer

这里是业务逻辑层:所有的逻辑都在这里进行。环视整个android项目,你会发现所有的interactors(use cases)都是在这里实现的。

该层属于纯java模块,没有一丁点的android依赖。所有的外部组件(components)都是以接口形式跟business objects联系。

clean_architecture_domain

Data Layer

应用所需的所有数据都来自该层,通过一个UserRepository的实现(其接口在domain layer),使用一个存储库模式(Repository Pattern),使用这样的策略:通过一个工厂依赖于具体的条件,获取不同的数据。

例如,当需要通过id获取user,如果user已经存在于缓存中,那么将会从磁盘中缓存的数据源中获取;否则,从云端获取,然后再缓存到本地磁盘。

这一切背后的理念是数据源对于客户端透明,就是说客户端不用关心数据是从内存、磁盘还是云端获取的,只要知道数据终会被获取就行了。

【译】Android架构之引入clean 架构_第4张图片
clean_architecture_data

注意:在代码方面,我已经实现了一个非常简单和原始的磁盘缓存,使用的是文件系统和android preferences,仅仅是出于学习目的。再次提醒,如果已有类库可以搞定需求就不要重复造轮子

Error Handling

这个话题仍在探讨中,如果你可以在这里分享下你的解决方案的话就更棒了。

我的策略是使用回调,因此,假如在data repository有事件发生,回调接口有两个方法onResponse()和onError()来进行处理。最后一个使用了一个叫“ErrorBundle”的包装类来封装异常:这种方法带来了一些困境,因为存在着一条直达显示层的回调链。代码可读性难以保证。

另一方面,我已经实现了一个事件总线系统,如果有错误发生会抛出一个事件。这个解决方案类似于GOTO。我的观点是,如果你订阅了多个事件而没有紧接着处理好的话,你会丢失一些事件。

Testing

关注于测试,我根据各个层的特点选择了几个解决方案:

  • Presentation Layer:使用android instrumentation和espresso进行综合测试和功能测试
  • Domain Layer:使用JUnit+mockito进行单元测试
  • Data Layer:Robolectric(因为该层有android依赖)+ JUnit + mockito进行综合和单元测试

Show me the code

我知道你一定想知道代码放哪里了,对吧?诺,这里有个github链接,我代码都放上面了。关于其中的文件结构,我要说几句,不同的层表示的使用的模块如下:

  • presentation:属于android 模块,代表presenttation层
  • domain:属于java模块,没有android依赖
  • data:属于android模块,数据源
  • data-test:data层的测试代码。由于使用Robolectric的一些限制,我不得不独立出一个java模块

Conclusion

正如Uncle Bob说的 "Architecture is About Intent, not Frameworks" ,我完全同意这种说法。当然,达到目的的途径有很多且各异(不同的实现),我们每天都面临着许许多多的挑战。但是,通过使用该技术,你可以确保你的应用:

  • 易于维护
  • 易于测试
  • 高内聚
  • 低耦合

总而言之,我强烈推荐你试一下,然后把你的结果和经历分享出来,包括你发现的其他更好的方法:我们知道持续改进是一件非常棒喝积极的事。

我希望本文对于有所裨益,并且我一如既往地欢迎任何反馈。

Source code

  1. Clean architecture github repository – master branch
  2. Clean architecture github repository – releases

Further reading:

  1. Architecting Android..the evolution
  2. Tasting Dagger 2 on Android
  3. The Mayans Lost Guide to RxJava on Android
  4. It is about philosophy: Culture of a good programmer

Links and Resources

  1. The clean architecture by Uncle Bob
  2. Architecture is about Intent, not Frameworks
  3. Model View Presenter
  4. Repository Pattern by Martin Fowler
  5. Android Design Patterns Presentation

你可能感兴趣的:(【译】Android架构之引入clean 架构)