刚开始,因为业务比较赶,我们也没有进行比较好的顶层设计,对代码的要求也是最低要求——完成功能开发就行了。这种短期设计也就造成了我们代码的扩展性几乎为零,稍微添加一点新功能,都要大动干戈。在后台系统架构从TCP转为HTTP时,这些缺点则被放大到极致……所以,我们只有重构了。近一个月来,我工作的重心便是好好规划和设计我们项目的代码结构,同时分享给我们的Android组并予以实行。因为研究了很多的架构,其中有Android相关的,也有非Android相关的,但凡稍稍对我设计架构有点点帮助的,我都翻了一遍。甚至还去了解了微信,微博的一些项目架构信息~

  然而在这个过程中,我发现,其实Android并没有像Java后台开发那样有着比较稳定的框架,可以直接套用,基本都是各有各的看法和规则。目前碰到的讨论最多的也就是所谓的MVC、MVP、MVVM这类的MVX框架。为了我们的中心思想做铺垫,那我们来一个个分析一下这些所谓的名门正派到底是不是真的如我们想的那样。

  一、MVC那些事

  我们先来看看MVC,因为MVC经常在Android开发中被提起。我们就先来看看MVC这种结构,通常情况下,也就是你面试的时候回答关于MVC的问题时,用到的答案。

  MVC 通信方式,是环形方式,如下左图所示:View 传送指令到 Controller;Controller 起到不同层面间的组织作用,用于控制应用程序的流程。它处理事件并作出响应。“事件”包括用户的行为和数据 Model 上的改变;Model 将新的数据发送到 View,用户得到反馈,所有通信都是单向的。

       关于Android架构那些事-LMLPHP          关于Android架构那些事-LMLPHP

理论上,还是挺合理的,但实际上,我们很容易就发现了他们耦合的比较深。通常一个改动,基本三大层级都要有改动,因为他们的触发具有很强的连贯性。更具体的情况,就是如果你是真的写代码而不是停在理论上,实际上MVC这种结构更应该用上右图去描述,也就是V的外部连接都是双向的,因为M有需要更改V的需求,同时Controller也有。

  好,我们现在移步到Android,假设我们套用MVC这种架构去处理Android的问题,显然,那一堆XML就是View,而Activity便是所谓的Controller,Model便是我们定义的那些数据对象。但是显然Android里面XML作为View层简直弱得有点螳臂当车的感觉,除了设置点属性,几乎不能做任何逻辑操作。所以,通常我们都会为了增强View的功能,而把Activity+XML作为View层。然而实际上,这样一个组合已经远远超过了View的能力范围了,因为Activity通常也要承担很多逻辑操作,即所谓的Controller的职责……Now we are totally mixed up!因为你已经无法准确分层了。因为MVC的套路主要是应用在强View的开发模式下的,比如桌面应用,因为只要View足够强才能发挥MVC的威力,显然Android原生不具备这个能力,除非你自己写一套View框架,这里说的不是那些什么注入的工具类,那些只是帮你减少代码量而已,并没有从根本上解决这个问题,这里的View框架,是一套增强Android原生View的框架。

  所以,显然原生MVC并不适合直接使用到开发过程中,这里加个原生MVC是针对于“那个标准答案”而言的,因为如果如果你衍生,修正过了就另当别论了~

  二、MVP那些事

  MVP可以说就是从MVC衍生过来,因为有问题就解嘛。既然MVC不够好,那我们就修正它!于是MVP就出来(虽然最初MVP也是如同MVC一样都是应用桌面应用的…)。如下左图所示:

关于Android架构那些事-LMLPHP        关于Android架构那些事-LMLPHP

  MVP 通信方式:各部分之间的通信,都是双向的;这里View 与 Model 不发生联系,全都通过 Presenter (你喜欢也可以叫Controller~)传递。这种结构便非常适合Android的View层,因为MVP结构中View 非常薄,不部署任何业务逻辑,基本属于”被动视图”(Passive View),即没有任何主动性,当然也就意味着 Presenter会非常的非常厚,所有逻辑都部署在那里。而实际上,我们使用的时候,则更趋于上右图,因为既然Presenter已经责任重大,再多点也没什么事,反而更好统一管理……于是我们便就把Model的能力也削弱一点,也就是Model层完全被动提供数据,类数据库模式。

  我个人认为升级到MVP其实已经挺好的了,至少结构上已经比MVC要更清晰一些了,唯一的问题是我们Presenter有点过重了,还是有改进的地方,我们会在后文一一道来。

  三、MVVM那些破事

  为什么用MVVM那些“破事”呢?因为我们发现至少目前,我没有看到一篇比较正常的关于MVVM在Android上的分析。因为现在Android里面现在一提到MVVM就是Dagger,好像Dagger=MVVM一样……但其实不是这样的,Dagger类工具,仅仅是为了实现View和Model的自动双向绑定而已,也就是本来应该调用view.setXXX去把Model的值赋给View去展示,现在不用了(这个“不用了”,仅仅是说程序员不用显性写这段代码而已……),所以MVVM中所谓的View-Model可以说就是Presenter,只是由于我们有了数据的双向绑定工具后,就使得上图中的Presenter与View的联系变成虚线了,而与Model保持双向连接,Model则与View绑定在一起。所以,与其说MVVM是MVP的优化,不如说是对MVC的优化。MVP和MVVM仅仅是通过两种不同的方式去优化MVC——MVP选择继续分层,而MVVM选择减少分层。也许,你看完上面可能对这些所谓的MVX依然没什么特别的感受。从分割线开始,我们便开始更深入地思考我们遇到的这些问题~


  无论是MVC,MVP还是MVVM,他们更像是一种软件开发的思想而不是一种模式。因为如果你把他定义为模式,你会发现他们在移动端,移动端有分IOS,Android和WP等,还有web端,PC端等实现的方式总是有一定的区别。就比如MVC,有些实现的是一种顺时针的方案,有些则会把mv隔离,全接在C上。就如同我上面举的例子一样,可能有些人会觉得,不对吧,不是另外一张图吗?但是当他们继续依赖搜索引擎的时候,他们就会凌乱了,因为有各种逻辑架构图而且各有各的道理,最要命的是没有人会说哪个是错误的。事实上,从你开始寻找他们的模版开始就已经误入歧途了。

  只有把这些所谓的架构看作是问题的一种解决思想时,我们才可以基于不同平台,不同的业务需求等现实而具体的问题去实现这种思想。说白了就是,马克思主义指导思想很好,但必须要符合中国国情。我们基于以上新的思想再回过头去看看我们之前碰到的问题,是不是很明朗?就比如MVC,无论它有多少中变种,它们都是为了更好地实现MVC分层解偶的理念而已。
  大家去网上搜一下android MVVM,有没有感觉几乎都涉及databinding,然后再介绍一番databinding的用法……然后就没了(稍微补充一下,这个问题你用google又会稍好一点~)。而很显然,基于我们新建立的思想,这些博文可以完全是片面且误人子弟的。因为databinding只是为了实现mvvm这种思想的一个环节的一个工具而已,那就是帮你把view和model绑定起来,如果没有这个工具,你要去实现mvvm的思想,你自己也会写一个binding的Util类去做这件事。其次,绑定完成后,就要操作跟业务息息相关的ViewModel。如果简单,那我们为何需要如此复杂的实现?(大家都知道,我们有些页面其实真的挺简单的,简单到你都不好意思说是你做了~)。如果业务逻辑复杂,你依然需要别的思想去分解这个庞然大物。 
  说这些,既是为了能够让大家多一个角度去看待这些所谓的模式。同时,也是想提醒大家不要太依赖网上的那些搜索,这其中既包括博客也包括github。因为Real大神真的很少,伪大神遍地都是。我们搜索尽量以参考为主,copy为辅。而不是反过来~这里顺便举个例子,如果哪位同学用过itemtouchhelper,并且还网上搜过,你就会发现,整个宇宙就那一个例子(你一搜就知道…),而实际上,只要看一下ItemTouchHelper的源码,你就会发现完全有更友好的办法~
   我们回归正题,那就是所有的软件架构以及开发思想,都是为了四个目的:Maintainable、Testable、Flexible 、Independent。也就是,使软件在满足需求的基础上能够更好地维护、测试、扩展以及相对独立。
  好维护意味着代码结构清晰,便于理解和修改;
  好测试意味着模块相对独立,耦合度低,外部依赖都是保持引用;
  好的扩展意味着接口规范,可以随时延伸业务;
  相对独立意味着与外部系统能相对独立地运行状态;
  其他都好理解,但是什么叫好的独立性?我们假设IOS也是用java开发的,你如何让你这一套代码能够平滑的从Android迁移到iOS?你是不是得定义一个比较好的视图接口以及一些别的涉及到系统API的接口,当迁移到IOS,你只要去实现这些接口就可以让代码正常的运行在IOS系统上。其实说白了就是要把自己的APP当做一个独立系统去开发,就是假设外部依赖都有可能改变,不仅仅是指后台,甚至还包括系统本身。我们都要能够应付得来。
  本来想继续写下去的,但是我想,还是把我的一张PPT放上来作为结束语,让大家慢慢体会吧。因为思想到实践总是会因为实际的环境而有所差异,但是,核心的那些主旨永远都不会变~
              关于Android架构那些事-LMLPHP
05-28 17:29