为什么要学习架构
首先我们要知道为什么要学习架构,无论是什么架构设计,其目的都是为了达到编码的最高境界——高内聚,低藕合,易测试,易维护。
而要达到这个终极目标,首先要理解的是每个部分代码各自负责些什么,以及该把哪些部分组合在一起。因此学习架构关键在两步:一是如何把缠在一起的代码拆分开,二是如何把拆开的代码再组合起来。
“
很多新手在刚做项目时,都会把所有的代码都写在一起,代码和思维都呈现出一种线性的形式,一切都是直来直往的。这样代码量确实少,写的时候也觉得方便,但是带来了几个致命的问题:
1. 当业务越来越复杂时,修改代码成了噩梦。同样的逻辑放在不同的地方,本来只用改一处的变成了需要改几百处。而又因为所有的逻辑都互相牵扯住,导致本来只想改一处的,结果却影响了几百处,甚至会导致根本无法进行修改。
2. 当需要做一个新功能时,却发现代码无法复用,明明是一样的逻辑也只能靠复制粘贴来堆积代码,并且这又为今后修改代码留下了隐患。
3. 当需要测试时却发现测试很难进行,每次修改一处代码后都必须进行重复的人工测试,无法进行自动化测试,模块和模块也无法拆开来进行独立的单元测试,每次都要整体的测一遍才能确保测试没有问题。
4. 当时间越来越遥远时,会发现代码可读性很低,漫漫千行代码和杂乱的代码结构,会发现明明是自己写的代码,却需要花很长时间去理解业务逻辑和查询处理位置,就更不要说让别人来接手或者理解你的代码了。
”
要学习的不单单是架构,而是思维方式
需要说明的是任何一种架构和模式其实都没有谁优谁劣之分,而且就算是同一种架构,也可以根据不同的使用场景来做不同的实现方式,这里并没有绝对的标准和概念定义。在应用型领域,定式和概念只应是在学习的过程中才存在的,真正将其用熟用活才是关键。要学习的不单单是架构,而是思维方式。模式终究只是一种设计理念的表现形式,学习再多的架构,你也只是多会用了几种工具而已,学习一种模式其实是在学一种思维方式。
软件的架构方式有很多种,从最开始的MVC模式,演化到MVP,然后到之后的MVVM,在不断的演化过程中其核心的思想就是降低各组件之间的耦合度,使得数据的流向更加的清晰明了。但并不是意味着一个比另一个高级,只是对于软件的架构方式有的不同的视角,针对不同的场景有了更多的选择方案。下面对主流的MVC,MVP和MVVM模式逐一进行简单的介绍。
MVC
经典原生架构
Model:是应用程序中用于存储和处理应用程序数据逻辑的部分,对应java bean以及一些类似repository类
View:是应用程序中处理数据显示的部分,对应xml布局文件
Controller:是应用程序中处理用户交互的部分。通常控制器负责从视图读取数据,控制用户输入,并向模型发送数据,对应Activity和Fragment
MVC(Model-View-Controller)是软件架构中最常见的一种框架,简单来说就是通过controller的控制去操作model层的数据,并且返回给view层展示。如上图,当用户出发事件的时候,view层会发送指令到controller层,接着controller去通知model层更新数据,model层更新完数据以后直接显示在view层上,这就是MVC的工作原理。
从上面这个结构来看,Android本身的设计还是符合MVC架构的,但是Android中纯粹作为View的XML视图功能太弱,我们大量处理View的逻辑只能写在Activity中,这样Activity就充当了View和Controller两个角色,直接导致Activity中的代码爆炸。相信大多数Android开发者都遇到过一个Acitivty或者Fragment有数以千行的情况,所以最终其实只是一个Model-View的结构。大部分都是通过Activity的协调,连接处理逻辑的。
MVC还有一个重要的缺陷就是,view层和model层是可交互的,这意味着两层之间存在耦合,耦合对于一个大型程序来说是非常致命的,因为这表示开发,测试,维护都需要花大量的精力。
MVP
从1个类变为N个类
�Model:用于存储和处理应用程序数据逻辑的部分
View:负责View的绘制以及与用户交互,对应activity和xml文件
�Presenter:负责完成View与Model间的交互和业务逻辑
MVP(Model-Presenter-ViewModel),和MVC最明显的差别就是view层和model层不再有交互,完全的解耦,取而代之的presenter层充当了桥梁的作用,用于操作view层发出的事件传递到presenter层中,presenter层去操作model层,并且将数据返回给view层,整个过程中view层和model层完全没有联系。看到这里大家可能会问,虽然view层和model层解耦了,但是view层和presenter层不是耦合在一起了么,其实不是的,对于view层和presenter层的通信,我们是可以通过接口实现的,具体的意思就是说我们的activity,fragment可以去实现定义好的接口,而在对应的presenter中通过接口调用方法。不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试。这就解决了MVC模式中测试,维护难的问题。
例如,原先的新闻列表只有一个NewsListActivity完成所有的业务逻辑和页面展示,现在会分成N个类
NewsListActivity(View)
NewsListPresenterImpl (Presenter)
NewsListModelImpl (Model)
NewsListView (Interface for View)
NewsListPresenter (Interface for Presenter)
NewsListMode (Interface for Model)
MVVM
Data Binding(数据驱动)
Model:用于存储和处理应用程序数据逻辑的部分
�View:负责View的绘制以及与用户交互,对应activity和xml文件
ViewModel:负责View和Model之间的通信,分离视图和数据
MVVM(Model-View-ViewModel),ViewModel是View的数据模型和Presenter的结合。View和Model之间通过Android Data Binding技术,实现视图和数据的双向绑定。ViewModel持有Model的引用,通过Model的方法请求数据,获取数据后,通过Callback(回调)的方式回到ViewModel中,由于ViewModel与View的双向绑定,使得界面得以实时更新。同时,界面输入的数据变化时,ViewModel中的数据也会同时更新。
采用ViewModel解决MVP模式中View(Activity)和Presenter相互持有对方应用的问题,界面由数据进行驱动,响应界面操作无需由View(Activity)传递,数据的变化也无需Presenter调用View(Activity)实现,使得数据传递的过程更加简洁高效。
MVC vs MVP vs MVVM
优势:
对于混乱的软件组织方式有了一个明确的组织方式,通过Controller来掌控全局
缺陷:
Controller的代码累积
View和model存在耦合
维护性差,不便于测试
MVP
优势:
降低耦合度,实现了Model和View真正的完全分离
模块职责划分明显,层次清晰
Presenter可以复用,一个Presenter可以用于多个View,而不需要更改Presenter的逻辑(在View的改动不影响业务逻辑的前提下)
如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)
缺陷:
额外的代码复杂度及学习成本
如果Presenter过多地与特定的视图的联系过于紧密,一旦视图需要变更,那么Presenter也需要变更了
不适用简单或小型的项目
MVVM
优势:
使得数据流的走向更加的清晰明了,同时也简化了开发,数据和视图只需要进行一次绑定即可
能把一些视图逻辑放在一个ViewModel里面,让很多view/ViewController进行重用
缺陷:
界面测试较为困难
小结
本文简单描述了从架构的角度去看待Android客户端的开发,希望大家在开发之前多从架构的角度去考虑,深入理解及应用才是王道。架构没有好坏之分,只有适合项目的架构才是好架构。经多方调研,笔者在基于研发云平台的研发云APP中采用的是MVP模式,在下一篇中,将对MVP模式进行详细介绍。