iOS开发 之 架构模式: MVC/MVP/MVVM
目录
为什么要谈架构
为什么要谈架构? 因为很多开发者和产品被架构"伤过"
当然如果你的项目只是1-2个人维护且view不超过20个的"小工程"
你或许没有意识到的它的存在, 因为只要你严格遵守Cocoa MVC你仍然可以写出不错的app
鉴于没人知道业务和产品的发展会是怎样? 所以在我们"真正"需要架构之前, 架构的第一个原则就是
不要架构, 请严格遵守Cocoa MVC
那么今天的讨论就到此为止了? 当然不是!
鉴于没人知道业务和产品的发展会是怎样? 所以在我们"真正"需要架构之前, 要了解到底有哪些"坑"
架构其实就是一种模式和经验的最佳实践, 而这正是移动开发所最缺乏的
鉴于移动开发作为软件开发细分的"新生力量", 它扔处于高速发展和持续动荡中, 很多"不算老"的经验被推翻, 新的偶像被树立, 因此每个公司每个产品每个开发者开发的方法也都不尽相同, 这些都大大增加了学习和维护的成本, 降低了共享和复用的效率
现实越是残酷和纷乱, 人们越是需要统一和高效的架构
鉴于业界圈内的一些大拿都有发文讨论此问题, 本文不敢造次, 只对已有的设计模式进行一些介绍和讨论
有哪些架构模式
今天所讨论的架构模式基于MV(X)模式, 主要有以下3种(如果你知道其他的模式和选择, 欢迎告诉我)
-
MVC
-
MVP
-
MVVM
这三种模式都由如下三个实体组成
-
Models - 负责主要的数据或者操作数据的数据访问层
-
Views - 负责展示层(GUI)
-
Controller/Presenter/ViewModel - 负责协调Model和View, 通常根据用户在View上的动作在Model上作出对应的更改, 同时将更改的信息返回到View上
其中MVC又是其他MV(X)的基础, 所以我们首先就来看看MVC模式
MVC
传统的MVC
传统的MVC模式是长这个样子滴(引自Wiki)
ios_architecture_01.png从箭头的指向可以明显地看出传统MVC的缺点
-
耦合性很强 - 三个实体间相互都有通信
-
复用性较低
理想的Cocoa MVC
Apple在iOS开发中对传统MVC进行了改进, "期望"的效果是这样的
ios_architecture_02.png即Controller是一个介于View和Model之间的协调器, 而View和Model之间没有任何直接的联系
这个模式解决了传统MVC部分耦合和复用的问题, 但是当你的逻辑不断地复杂时
- 很容易就变成了这种MVC(Massive View Controller)
ios_architecture_03.png对于这种理想的MVC, 斯坦福大学公开课: iOS 7应用开发有更详细的说明
实际开发中的Cocoa MVC
虽然理想化的MVC有胖VC的风险, 但已经算是蛮不错的结构了(胖VC可以转嫁成胖Model, 并不断重构和抽象VC中的逻辑)
但是当你真正开发iOS开发时, 你会发现实际的Cocoa MVC并不像人们期望的那样
ios_architecture_04.png怎么回事? View和View Controller被紧紧绑在了一起?! 说好的分离, 说好的解耦, 说好的复用, 一切都是骗人的!
鉴于Cocoa的这种设计, iOS应用架构谈 view层的组织和调用方案一文中有这样一种理解和解释:
将与ViewController绑定的View理解成ViewContainner, 那么ViewController就还是那个Controller了
但是这样的理解并不能掩盖Controller知悉View内部实现而破坏封装的事实, 如以下写法所见
var userCell = tableView.dequeueReusableCellWithIdentifier("identifier") as UserCell
userCell.configureWithUser(user)
所以总体来说, 实际开发中的Cocoa MVC并不是严格意义上的MVC, 它在实际开发中有如下一些问题
-
耦合性 - View和Model确实是分开的, 但是View和Controller却是紧密耦合的
-
测试性 - 由于只有Model的完全独立的, 所以只有对Model进行单元测试是相比比较容易的
-
复用性 - 尤其是View的复用, 这点开发过Android的同学, 都知道xml的复用相比xib或手写布局强太多
MVP
MVP将MVC中的Controller换成了Presenter, 结构如下
ios_architecture_05.png看这个轮廓, 不就是MVC么? 简单地说, MVP就是理想化的MVC!
那么MVP是如何应用到iOS开发中来的呢? 简单地说, MVP中就是将MVC中的View Controller当做View!
这样, MVP就解决了实际开发中Cocoa MVC的几个缺点, 一切看起来如此地完美? 错!
-
增加了代码量 - 单单增加Presenter就会增加许多新的文件和类, 更何况之前View的delegate从View Controller变成了Presenter
-
增加了第三方库接入成本 - 鉴于以往的开发经验, 第三方UI库大多是基于Cocoa MVC(注意这里是实际而非理想版)的, 所以如果是用继承方式接入的话, 会带来额外成本(至于继承的优劣, 本文暂不深入讨论)
MVVM
鉴于MVP或者说是理想的Cocoa MVC已经是比较完美的结构模式了, 那么为什么还又多出一个MVVM来呢?
因为不管是MVC还是MVP都有一个问题, Controller和Presenter这个"协调员"太关键了, 代码稍微写多点, 它们就变成了Massive Controller或者Massive Presenter
那么如何给Controller或Presenter减负呢?
答案就是让View和Model自己去沟通, 让Controller和Presenter从"协调员"降级成"介绍者"
ios_architecture_06.png那么如何理解iOS开发中的MVVM呢? (这次我就当回搬砖的, 引自iOS Architecture Patterns)
So what is the View Model in the iOS reality? It is basically UIKit independent representation of your View and its state. The View Model invokes changes in the Model and updates itself with the updated Model, and since we have a binding between the View and the View Model, the first is updated accordingly.
请注意这里的accordingly, 因为它指出了MVVM最重要的一个特点: 响应式
MVVM几个热门的实现都是完全的函数响应式编程
-
android: ReactiveX/RxJava, square/retrofit
MVVM这么强大, 难道会是"银弹"不成?
遗憾地说, MVVM也不是"银弹", 这是因为在实际的移动平台开发中, 从主流的Objective-C和Java切换至函数响应式思维, 都有不小的学习和培训成本
鉴于此, ReactiveCocoa或者RxJava应该根据项目的实际情况, 由小到多地逐渐在开发中应用开来, 而不必全盘照搬
小结
讨论了这么多, 其实我想说我们的项目还是完完全全的Cocoa MVC
但是了解其他架构模式, 仍是有意义的, 当你知道他们的优缺点, 在面临新的问题时, 你才能够从容地做出正确的选择和判断
架构的讨论远不止今天这些"皮毛", 欢迎大家一起讨论和分享
参考
更多文章, 请支持我的个人博客