学习 CleanArchitecture 心得体会

作者: brzhang | 来源:发表于2016-05-25 18:36 被阅读11034次

最近 Android-CleanArchitecture 闹得是沸沸扬扬,然而笔者也不甘寂寞,一直在研究这个东西,也fork过一些关于cleanArchitecture开源的项目进行了学习:

比如 android10 https://github.com/android10/Android-CleanArchitecture
比如 googlesample https://github.com/googlesamples/android-architecture/tree/todo-mvp-clean/
比如 dmilicic https://github.com/dmilicic/Android-Clean-Boilerplate

关于探讨CleanArchitecture架构方面的文章也很多,但是,究其源头,无非都是出自uncle-bob 叔叔的这篇 https://blog.8thlight.com/uncle-bob/2012/08/13/the-clean-architecture.html

至于大家为什么倾向于cleanArchitecture,那一定是有他的道理的。就好比,对比传统开发的MVC开发方式,你会得到以下好处。

代码复用性更高
更易于测试
耦合度更小

下面这幅图,是googlesample下面的了。


googlesamples

下面这幅图,是uncle-bob画的了。


uncle-bob

细心的你已经发现了,这两个图其实是一个意思。从大的方向上看,都是三层结构。

DataLayer

最底层,完全不知道有DomainLayerPresentationLayer的存在,听到这里,你还在怀疑这个架构的可测试性耦合度低吗?那么DataLayer的主要职责是什么?
1、从网络获取数据,向网络提交数据,总之就是和网络打交道。
2、从本地DB,shareprefence等等,内存等,总之就是本地获取数据,缓存数据,总之就是和本地数据打交道的。
这也就是你为什么看到很多Android-CleanArchitecture 的 package里面有一个local ,和一个remote了,然而是否有必要分的这么细,个人习惯啊~,不强求。反正这一层如果出现了 anroid.os***,我就更你拼了,对不起,你已经偏离了Android-CleanArchitecture了。

DomainLayer

中间层,他完全不知道有一个PresentationLayer存在,他只知道,有DataLayer,他可以基于这些数据,建立很多玩法,比如去网络拿一堆名人回来,然后将这些数据缓存到本地,在比如,他写了一篇黑某明星的文章,将文字发布到网上等等。因此他的主要职责是:
1、控制DataLayer对数据做增删改查,没错,就这么简单,然后就没有然后了。
2、真的没有了,不骗你,但是这一层如果出现了 anroid.os***,我就更你拼了,对不起,你已经偏离了Android-CleanArchitecture了。

PresentationLayer

最上层,他知道DomainLayer,有人要问了,那么他知道DataLayer,回答,他知道你妹~ 他累不累啊,要知道这么多?
因此,它只知道DomainLayer,那么他的职责有哪些?
1、通知DomainLayer有活干了,根据DomainLayer反馈变化界面
2、通知DomainLayer有活干了,根据DomainLayer反馈变化界面
3、通知DomainLayer有活干了,根据DomainLayer反馈变化界面
这年头,重要的时间一定要说三遍,而且,就是这么任性~~

分析了每层之后,我们发现,依赖的关系是 PresentationLayer --> DomainLayer --> DataLayer 的。
DomainLayer --> DataLayer 不知道有android平台的存在。
因此,只要我们围绕这个原则去做架构,那么就称的上是Android-CleanArchitecture。

这里是我根据Android-CleanArchitecture思想,实现了一个,里面附带了demo,https://github.com/bravekingzhang/CleanArch

相关文章

网友评论

  • owant:在domain发现了android.content.Context:cry:
  • 宗仁:presentation layer和data layer都是依赖 domain layer的。。
  • 李贤俊:通俗易懂,贼搞笑:joy:
  • 刺鸟开源:认真看完博客,又去github仔细看了代码,写的挺好
    31e8188ff961:文章写的很好,简明易懂
    presenter 持有data层的引用,虽然看出来这个引用是必须的,但真的不会破坏设计的美感吗?而且presenter知道了data里面的东西,如何有强硬的方式让程序员知道present最好不要直接用data里的东西呢?,比如data里的bean等
    brzhang:@刺鸟开源 谢谢谬赞
  • 李简书:想请教一个问题,一些全局共用的用户信息等内容,应该在data layer层保存吗?还是在domain layer (usernodel);里?
  • 热血沸腾:MVP 各部分通信都是双向的,互相知道的。 问题来了,CleanArchitecture 如何用代码实现,单向通信 .
    brzhang:@热血沸腾 对,view不要和model扯上什么直接关系,不然,和之前的MVC又有何区别。就又耦合了。
    热血沸腾:@brzhang Persenter持有View引用, View也持有Persenter引用。 P与V之间是双向通信。 P与M 之间可以单向。
    brzhang:@热血沸腾 MVP 并不是双向的,可能你还需要查阅相关资料
  • 欢乐的乐:请问android-cleanArchitecture是一个框架的标准还是什么?有点不是很明白
    brzhang:@欢乐的乐 只能说是一个标准,是一种架构思想。
  • 9a76ec07b270:DataLayer层除了网络部分可以完全不依赖android.os,除此之外,无论是本地文件,还是数据库,还是缓存,我实在想不出怎么样可以不依赖android.os去做,还请赐教。
  • 向晚轻烟:要是加上泛型就更完美了
  • 北方南山:请教一个问题。https://github.com/android10/Android-CleanArchitecture
    UserDetailsActivity 里面初始化的时候,已经知道用户id这一个参数了,然后他的GetUserDetails 类是依靠构造函数把id 传进去的。
    问题是:GetUserDetails 是由view 层 初始化好传到presenter的构造函数的,但很多页面不一定都在GetUserDetails 实例化之前知道参数。比如第二个接口的参数是第一个接口的返回值,这样第二个UseCase 不可能事先通过构造函数把参数传进去,所以,这个参数的有更好的解决办法吗?我现在是在 UseCase 里增加了一个方法,代码如下,希望可以多交流交流:
    ```
    public abstract class RxBaseCase {

    private Subscription mSubscription = Subscriptions.empty();

    protected RxBaseCase() {
    }

    public abstract Observable buildCaseObservable();

    public abstract RxBaseCase initParams(String... paras);

    public void execute(Subscriber subscriber) {
    this.mSubscription = this.buildCaseObservable()
    .subscribe(subscriber);
    }

    public void unsubscribe() {
    if (!mSubscription.isUnsubscribed())
    mSubscription.unsubscribe();
    }
    }
    ```
  • 北方南山:有三点疑问:
    1. data->domain->presenter,下层不知道上层,也不存在断层依赖。这样的实现确实很好,但是android10 大神[https://github.com/android10/Android-CleanArchitecture] 实现的presenter 确实有对data moudle的引用。
    2. data和domain层不能出现anroid.os*,看android10 大神 [https://github.com/android10/Android-CleanArchitecture] 和googlesample [https://github.com/googlesamples/android-architecture/tree/todo-mvp-clean/] 确实没有出现.os* 相关的import。但是 android10 大神 使用了 android.content.Context,googlesample使用了dbhelper 等相关。
    3. 还有一篇文章 http://www.jianshu.com/p/f3f0eccbcd6f 是说 rxjava封装的,不打破链式结构,但是 android 10 大神的domain层,UserCase 在 presenter层已经不能实现链式结构了,比如说使用 flapmap 连续三个请求。使用UserCase 必须在Subscriber 的回调函数里执行下一个请求。请看这边文章 http://www.jianshu.com/p/0f926fda682b
    北方南山:@brzhang 是呀,好用就好,哪里有什么一定怎样的。谢谢啦
    brzhang:@北方南山 那并没有什么关系,因为这clean描述的是那种由外向内的依赖关系,我这么实现ok,别人那么实现不能说打破了依赖,主要看你的是否存在了太多的耦合了,一个db,一个pref都是不避免的要拿到context,紧紧是个context,你可以通过dagger注入,依赖了android层对吧,关系大不?并不大,你们往往喜欢去纠结这些,而忘记clean的最核心的,由外向内依赖就好。
  • initialjie:有个地方不太对,DataLayer是可以有android相关的东西的,比如本地DB,shareprefence等等。
    DataLayer对外职责就是按照定义的Repository接口提供实现而已,至于它究竟是怎么实现的。Domain,presenter不需要知道。所以即使在其它平台,DataLayer只需要修改具体的实现细节而已。
    相反Domain就是纯JAVA实现了,不依赖任何外部框架与库,最大可能保证其可移植性,因为里面都是最基本的业务用例。
    f9d3d9cdfec1:@brzhang 你说的很有道理,但是,本地数据的操作应该放在哪里呢?
    brzhang:@initialjie 另外,你绝不觉得,C->B->A ,结果,你的C,A层依赖于android层的东西,反而,中间人B不知道,这个设计不知道是否怪怪的,在者,测试的时候,你对A层测试,是否需要加入android框架呢,合适吗?
    brzhang:@initialjie DataLayer是可以有android相关的东西,但是不建议有 ,为了一个sharepref的东西 ,引入一个context,并且和android框架糅合上了,这个不值得 ,而且,本地存储的方式很多,并非文件就不能存储,你可以有这方面的思考,没问题的 。
  • cuixbo:可以这么理解么?
    其实它是将MVP改变了一下:
    M:DataLayer+DomainLayer
    V+P:PresentationLayer
    其本质依然是MVP架构,只是对M细分了
    猫疏:没错
    brzhang:@崔小波 mvp只不过是presenter层:smile:
  • cuixbo:反正这一层如果出现了 anroid.os*,我就更你拼了 :+1:

本文标题:学习 CleanArchitecture 心得体会

本文链接:https://www.haomeiwen.com/subject/mmutdttx.html