MVC与MVVM

从MVVM到RxSwift

最近一段时间正在研究响应式编程,目前iOS开发中用的比较多的响应式编程框架有ReactiveCocoaRxSwift两种。我在学习RxSwift使用的过程中发现,关于该框架的文章大多比较晦涩,内容大多偏向于框架原理,在结合MVVM设计模式使用上却没有过多深入。本篇抛砖引玉,从MVVM解决的问题开始,逐步讲到如何将RxSwift结合MVVM使用到实际开发中。


MVC与MVVM

说MVC框架不好用是没有用好MVC框架
但是MVVM会让复杂工程的构架变得更加简单直观

MVC和MVVM其实之间并没有优劣之分,只是适用的场景不同。一门技术的出现必定是为了解决一类问题,抛开开发场景谈框架优劣就是耍流氓。


MVC解决的问题

比如,我们须要开发一个完整功能的软件,它会包含:

  • 获取数据(网络请求,数据库读取,本地文件读取)
  • 初始化并加载和配置视图
  • 将获取的数据展示到视图上
  • 将变更的数据反馈给数据库

假如没有MVC或者我偏不使用任何设计模式,将所有流程全部写在Controller中 我真是哔了狗才会这么做 ,进行编程我会怎么做:

  • 写若干个获取数据(网络请求等)的方法
  • 逐一初始化并配置UIKit库给定的视图控件
  • 使用得到的Dictionary或者Array对控件逐一赋值
  • 获取TextField的文字,Switch上的Bool值,并组装成格式化的数据上传或者存储

这样的代码会出现什么问题:

  • 这个文件中的代码会轻易超过1500行(代码难以阅读)
  • 产品说辛苦大家一下我们要改个小需求,于是我加了三天班;UI说亲爱的我想变一下页面布局,于是我又加了三天班(代码难以修改)
  • 有个视图一样但是逻辑不同的需求,我只好从源代码复制粘贴加以修改重新实现(代码难以移植)
  • 出现了一个了不得的BUG,我再加三天班(代码难以维护)
  • 我由于加班劳累过度住院了,接手该项目的程序员在看了代码之后立即递交了辞职报告(代码难以交接)

这种将所有代码放在一起的写法违背了程序设计时最基本的思想:高内聚,低耦合
所以MVC的出现就是为了写出模块化的程序,将模块之间的耦合降低,模块与模块的联系通过简单的接口进行暴露,Model只处理数据部分,View只处理视图部分,他们两部分在Ctroller中相互发生联系。
在Controller中规定Model何时初始化、何时赋值给View进行展示的逻辑,叫做 业务逻辑


MVC无法解决的问题及MVVM

MVC的构架能够解决目前软件设计的绝大部分问题。
但是遇见一个功能复杂,业务逻辑繁琐的功能,即便MVC已经将它拆分成Model-View-Ctroller三部分,但Controller中的代码仍然会轻易超过800行。
所以,为了 高内聚,低耦合 ,为了代码更容易维护和修改,为了不加班, 我们需要对功能进行进一步拆分。将功能拆分为: <center>数据模型 -- 视图 -- 视图控制器 -- 业务逻辑</center>
正式因为页面业务逻辑太复杂,才使得MVC中的Ctroller过于厚重,所以我们要将业务逻辑拆分出来进行单独处理
所以MVVM这种在MVC基础上的设计模式应运而生。

MVC与MVVM之间最大的区别在于,MVC中用于管理业务逻辑的是Controller,MVVM中用于管理业务逻辑的是ViewModel。从MVC到MVVM实际上就是把MVC中Ctroller管理的业务逻辑拆分出来到ViewModel中。

如果要弄明白如何将业务逻辑拆分出来,就要先弄明白业务逻辑在代码中是以什么方式存在的,业务逻辑之于服务器是什么关系,业务逻辑之于视图是什么关系。


应用之于服务器的关系:什么是业务逻辑

服务器之于应用的关系:

  1. 传递数据给应用
  2. 接收并处理,应用传入的数据及事件
  3. 告诉应用什么时候启动什么事件

前两个都很好理解,这是我们写程序时的日常工作。第三个‘告诉应用什么时候该启动什么事件’都是指哪些呢:

  • 基于HTTP/HTTPS响应的服务器,会告诉应用,网络请求的成功状态及请求结果
  • 基于TCP/UDP长链接的服务器会将事件发送给应用,应用在客户端给出对应的状态

简化一下就是:

服务端在 某一时刻 将数据传递给应用,客户端将 数据转化为状态 展示给用户
客户端在 某一时刻 从视图 接收到用户状态 ,并转化为数据提交给服务器

数据是由Model处理的。那么 状态和时间的处理,就是业务逻辑


ViewMode与View的关系

既然业务逻辑需要处理时间和状态,并展示到视图上;同时,视图需要向业务逻辑告知自己的状态更新,因为这些状态要被转化成数据提交到服务器。
简化一下就是:

View需要调用VM的某些功能
VM也需要调用View的某些功能

这种双向操作一般我们会使用delegate或者block
其实在MVVM中使用这两种方式实现互绑也未尝不可,只不过有些麻烦,因为他们都是在ViewController中创建的,所以使用这两种方式的话,我们需要定义一个XXViewDelegate和一个XXControllerDelegate,或者使用定义block,然后将block相互赋值,或者我们可以使用Notification...

上边的都是废话

这种双向关系使ViewModel好像View的一个映射,可以通过ViewModel获取到View的状态,也可以通过操作ViewModel操作View

这种相互响应的关系其实就是响应式关系

我们可以通过ReactiveCocoa框架或者RxSwift框架使View和VM之间快速建立起这种关系。

*注:那些不关乎业务逻辑的视图状态,比如动画效果等,交给视图自身去管理。


两种构架在工程中的应用原则

归根结低还是开头的那一句话:

说MVC框架不好用是没有用好MVC框架
但是MVVM会让复杂工程的构架变得更加简单直观

在同一个工程中MVC和MVVM可以混合使用,在实际客户端开发中,如何选择一个合适的构架给功能,关系到功能的开发成本,复杂度,可维护性和可移植性,设计模式的选择其实就是在这几个方面做权衡。
一般遵循的原则是:

工程第一,构架第二,代码第三

工程第一:开发时需要保证代码按期提交,不延误工程进度,且bug率低。如果时间紧张,就需要选择自己熟悉的构架来提高开发效率,尽管这套框架不是最适合这个工程的,但是工程进度比合适的构架要重要。
构架第二:在保证工程能按期完成的情况下,需要有一套合适的构架来提升工程的可维护性和可移植性。
代码第三:这是一个人的习惯问题,是一个程序员每时每刻都需要规范的行为,几乎是一种无意识行为,如何使命名变量及方法名称让代码更具有可读性,如何写注释让维护者或者将来自己维护代码更能理解编写意图。这种习惯需要时刻培养,却不能急于求成。毕竟,完成工程是眼前的事,写出的代码优不优雅,是一辈子的事。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容