这些年,参与的项目大大小小应该有六七个。所采用的项目架构,也是从 MVC 到 MVP ,后来使用 ReactNative 进行跨平台开发,再到后来回到原生,使用 MVVM。本节,打算聊一聊我的项目架构的演变之路。
MVC
M, Model,主要负责进行数据访问,产生数据;C,Controller,主要负责对接 View 和 Model,将 Model 反映到 View 上,或者响应 View 上的动作,修改 Model,处理业务;V,即 View,主要负责 UI 渲染。
MVC组件之间的典型合作上图来自维基百科。我们可以看到一个典型的 MVC 模式下的数据流向。上图中,View 监听 Model 的数据变化,然后进行 UPDATES 工作,这其中也会有业务逻辑处理。事实上,有些时候我们还需要对 Model 层的数据做进一步处理然后再做前端展示,这也是部分业务逻辑。
所谓架构只是一种设计理念,目的就是在于保持逻辑的清晰,面向改变易扩展,功能易复用。对于 MVC 模式而言,看上去各司其职,请求数据的产生数据;负责逻辑的处理逻辑,负责渲染的进行渲染,清晰明了。
然而,View 层对 Model 有着很强的依赖。为了能够使得 Model 发生的变化及时反映到到 View 上,View 需要注册成为观察者到 Model 上。鉴于这种关系,View 、 Model 需要互相持有对方的引用。
image
首先,这种相互持有引用会导致层次的独立性、可重用性要降低一些,而且这种行为也是危险的,暴露更多的能力给 View,可能使得部分本应在 Controller 处理的逻辑放在 View,因为这样做确实更加快捷方便。这样做也会带来一个很严重的问题:View 会客串 Controller 的角色,从而越来越臃肿,解耦能力越来越弱。
MVP
使用 MVC 没多久,同事建议组长采用 MVP 开发模式,于是,就是这么快的就跳转到了 MVP 的阵营。当时最感兴趣的还是这种架构中突出的对接口的应用,面向接口的编程思想。
面向接口的编程,实际上是 Java 开发一直所倡导的。优势在于解耦,降低依赖关系。但是也会让开发工作更加复杂。
上图同样来自维基百科。相较于 MVC 模式,它切断了 View 层和 Model 层的直连。Model 和 Presenter 之间, Presenter 和 View 之间相互暴露接口,并通过接口相互访问,接口构成了它们通信的通道。与 MVC 类似, Modle 负责数据访问和处理;Presenter 像胶水一样,把 Model 和 View 绑在一起,它主要处理业务逻辑,对 View 提供处理好的数据,对 Model 请求数据;View 处理 UI 渲染。
后来的开发过程中,很少使用 MVC,当然并不是因为觉得它比 MVP 差。更多的,自己是想增强接口使用的意识,以及对新事物的一种探索欲。现在想想,其实它们更多的是理念上的不同,如果控制的足够好,各有千秋吧。下面我们就来比较一下。
MVC vs MVP
这两种结构,都体现了良好的解耦理念。将一个需求拆分成数据访问模块、UI渲染模块、业务处理模块,相对独立,分工明确,各谋其政。同时,各个模块之间又可以在一定程度上相互组合,尽可能地进行功能复用。但是,在具体使用上,我觉得还是有一些偏好。
保证结构的清晰是一件非常重要的事,对此,大多数情况下宁愿牺牲性能。这一点上我认为 MVP 要比 MVC 做的好,职责划分的更加清晰。Activity 只负责渲染,很清爽;当然,这就意味着更多的处理逻辑需要搬到 Presenter 中去;Model 只负责向 Presenter 提供数据支持。为了保证逻辑的清晰,整个过程却会显得复杂,有些地方甚至没必要。View 层明明只是需要改一下 Model 的数据,都需要 Presenter 代劳。显然,这种清晰性牺牲了高效。
结构上的清晰,职责上分工更加明确,更细,也应该就意味着更好的复用性,更加灵活。但是,同样这也未必总是需要的。如果一个需求交互不多,Presenter 可能就会非常小,又何必将一个文件能够搞定的事一定要分成三个文件去完成?
MVVM
MVVM 是由 MVP 演化而来的。我觉得它主要解决了 MVP 没有很好解决的两个问题:
- 对于 MVP 的 Presenter 层,由于要处理所有业务逻辑,又要完成 Model 和 View 的沟通,最终可能也会非常臃肿。
-
通常情况下,我们总是要通过 findViewById 找到控件,然后进行数据填充,如果一个页面很复杂,需要填充的数据很多,这样在 View 层会显得很不优雅。
这样,就交给 MVVM 来解决吧。
MVVMPattern
上图(来自维基百科)中很好的解决了这两个问题。ViewModel 集合了 Presenter 的能力,同时兼顾了 View 需的数据基础。它将数据直接绑定到 View上,这种绑定是一种双向绑定,即数据的变化会自动导致 UI 的刷新,而 UI 上的动作,同样会自动调用响应的绑定的函数修改数据。
Android 所提供的 DataBinding 技术很好的体现了这一点。之前翻译过一篇官网上关于 DataBinding 的介绍,感兴趣的可以看一下。现在 View 层可以更加清爽,不用再为了填充数据而找出所有的 View,一个一个填充,而 View 也会由于某个用户动作而自动回调修改数据,这一切都是自动完成的。当然,有利必有弊,这种框架的使用,首先需要我们去了解它的特性;而且自动完成,未必会有我们手动完成效率高,多半会牺牲部分性能。
小结
架构, 一种理念,一种思想,一个工具。它的目的,旨在帮助我们更好地面对、处理变化;更加清晰地认知我们正在做什么。
工具是有了,这只是一个基础。更为关键的我觉得还是对这种工具的把控能力。因此,也并非是说你使用了 MVVM , 你的项目应对变化的能力就一定会比 MVC 好。对于需求的理解,将需求进行抽象的能力,以及对于技术扎实的能力,这些都将会对架构的把控提出挑战。
网友评论