Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >被误解的 MVC 和被神化的 MVVM(一)

被误解的 MVC 和被神化的 MVVM(一)

作者头像
HelloWorld杰少
发布于 2022-08-03 08:22:17
发布于 2022-08-03 08:22:17
3790
举报
文章被收录于专栏:HelloWorld杰少HelloWorld杰少

MVC 的历史

MVC,全称是 Model View Controller,是模型 (model)-视图 (view)-控制器 (controller) 的缩写。它表示的是一种常见的客户端软件开发框架。

MVC 的概念最早出现在二十世纪八十年代的 施乐帕克 实验室中(对,就是那个发明图形用户界面和鼠标的实验室),当时施乐帕克为 Smalltalk 发明了这种软件设计模式。

现在,MVC 已经成为主流的客户端编程框架,在 iOS 开发中,系统为我们实现好了公共的视图类:UIView,和控制器类:UIViewController。大多数时候,我们都需要继承这些类来实现我们的程序逻辑,因此,我们几乎逃避不开 MVC 这种设计模式。

但是,几十年过去了,我们对于 MVC 这种设计模式真的用得好吗?其实不是的,MVC 这种分层方式虽然清楚,但是如果使用不当,很可能让大量代码都集中在 Controller 之中,让 MVC 模式变成了 Massive View Controller 模式。

Controller 的臃肿问题何解?

很多人试图解决 MVC 这种架构下 Controller 比较臃肿的问题。我还记得半年前 InfoQ 搞了一次移动座谈会,当时BeeFramework 和 Samurai-Native 的作者 老郭 问了我一句话:「什么样的内容才应该放到 Controller 中?」。但是当时因为时间不够,我没能展开我的观点,这次正好在这里好好谈谈我对于这个问题的想法。

我们来看看 MVC 这种架构的特点。其实设计模式很多时候是为了 Don't repeat yourself 原则来做的,该原则要求能够复用的代码要尽量复用,来保证重用。在 MVC 这种设计模式中,我们发现 View 和 Model 都是符合这种原则的。

对于 View 来说,你如果抽象得好,那么一个 App 的动画效果可以很方便地移植到别的 App 上,而 Github 上也有很多 UI 控件,这些控件都是在 View 层做了很好的封装设计,使得它能够方便地开源给大家复用。

对于 Model 来说,它其实是用来存储业务的数据的,如果做得好,它也可以方便地复用。比如我当时在做有道云笔记 iPad 版的时候,我们就直接和 iOS 版复用了所有的 Model 层的代码。在创业做猿题库客户端时,iOS 和 iPad 版的 Model 层代码再次被复用上了。当然,因为和业务本身的数据意义相关,Model 层的复用大多数是在一个产品内部,不太可能像 View 层那样开源给社区。

说完 View 和 Model 了,那我们想想 Controller,Controller 有多少可以复用的?我们写完了一个 Controller 之后,可以很方便地复用它吗?结论是:非常难复用。在某些场景下,我们可能可以用 addSubViewController 之类的方式复用 Controller,但它的复用场景还是非常非常少的。

如果我们能够意识到 Controller 里面的代码不便于复用,我们就能知道什么代码应该写在 Controller 里面了,那就是那些不能复用的代码。在我看来,Controller 里面就只应该存放这些不能复用的代码,这些代码包括:

在初始化时,构造相应的 View 和 Model。

  • 监听 Model 层的事件,将 Model 层的数据传递到 View 层。
  • 监听 View 层的事件,并且将 View 层的事件转发到 Model 层。
  • 如果 Controller 只有以上的这些代码,那么它的逻辑将非常简单,而且也会非常短。

但是,我们却很难做到这一点,因为还是有很多逻辑我们不知道写在哪里,于是就都写到了 Controller 中了,那我们接下来就看看其它逻辑应该写在哪里。

如何对 ViewController 瘦身?

objc.io 是一个非常有名的 iOS 开发博客,它上面的第一课 《Lighter View Controllers》 上就讲了很多这样的技巧,我们先总结一下它里面的观点:

  • 将 UITableView 的 Data Source 分离到另外一个类中。
  • 将数据获取和转换的逻辑分别到另外一个类中。
  • 将拼装控件的逻辑,分离到另外一个类中。

你想明白了吗?其实 MVC 虽然只有三层,但是它并没有限制你只能有三层。所以,我们可以将 Controller 里面过于臃肿的逻辑抽取出来,形成新的可复用模块或架构层次。

我个人对于逻辑的抽取,有以下总结。

1.将网络请求抽象到单独的类中

新手写代码,直接就在 Controller 里面用 AFNetworking 发一个请求,请求的完数据直接就传递给 View。入门一些的同学,知道把这些请求代码移到另外一个静态类里面。但是我觉得还不够,所以我建议将每一个网络请求直接封装成类。

把每一个网络请求封装成对象其实是使用了设计模式中的 Command 模式,它有以下好处:

  • 将网络请求与具体的第三方库依赖隔离,方便以后更换底层的网络库。实际上我们公司的 iOS 客户端最初是基于ASIHttpRequest 的,我们只花了两天,就很轻松地切换到了 AFNetworking。
  • 方便在基类中处理公共逻辑,例如猿题库的数据版本号信息就统一在基类中处理。
  • 方便在基类中处理缓存逻辑,以及其它一些公共逻辑。
  • 方便做对象的持久化。

大家如果感兴趣,可以看我们公司开源的 iOS 网络库:YTKNetwork。它在这种思考的指导下,不但将 Controller 中的代码瘦身,而且进一步演化和加强,现在它还支持诸如复杂网络请求管理,断点续传,插件机制,JSON 合法性检查等功能。

这部分代码从 Controller 中剥离出来后,不但简化了 Controller 中的逻辑,也达到了网络层的代码复用的效果。

2.将界面的拼装抽象到专门的类中

新手写代码,喜欢在 Controller 中把一个个 UILabel ,UIButton,UITextField 往 self.view 上用 addSubView 方法放。我建议大家可以用两种办法把这些代码从 Controller 中剥离。

方法一:构造专门的 UIView 的子类,来负责这些控件的拼装。这是最彻底和优雅的方式,不过稍微麻烦一些的是,你需要把这些控件的事件回调先接管,再都一一暴露回 Controller。

方法二:用一个静态的 Util 类,帮助你做 UIView 的拼装工作。这种方式稍微做得不太彻底,但是比较简单。

对于一些能复用的 UI 控件,我建议用方法一。如果项目工程比较复杂,我也建议用方法一。如果项目太紧,另外相关项目的代码量也不多,可以尝试方法二。

3.构造 ViewModel

谁说 MVC 就不能用 ViewModel 的?MVVM 的优点我们一样可以借鉴。具体做法就是将 ViewController 给 View 传递数据这个过程,抽象成构造 ViewModel 的过程。

这样抽象之后,View 只接受 ViewModel,而 Controller 只需要传递 ViewModel 这么一行代码。而另外构造 ViewModel 的过程,我们就可以移动到另外的类中了。

在具体实践中,我建议大家专门创建构造 ViewModel 工厂类,参见 工厂模式。另外,也可以专门将数据存取都抽将到一个 Service 层,由这层来提供 ViewModel 的获取。

4.专门构造存储类

刚刚说到 ViewModel 的构造可以抽奖到一个 Service 层。与此相应的,数据的存储也应该由专门的对象来做。在小猿搜题项目中,我们由一个叫 UserAgent 的类,专门来处理本地数据的存取。

数据存取放在专门的类中,就可以针对存取做额外的事情了。比如:

  • 对一些热点数据增加缓存
  • 处理数据迁移相关的逻辑

如果要做得更细,可以把存储引擎再抽象出一层。这样你就可以方便地切换存储的底层,例如从 sqlite 切换到 key-value 的存储引擎等。

小结

通过代码的抽取,我们可以将原本的 MVC 设计模式中的 ViewController 进一步拆分,构造出 网络请求层、ViewModel 层、Service 层、Storage 层等其它类,来配合 Controller 工作,从而使 Controller 更加简单,我们的 App 更容易维护。

另外,不知道大家注意到没,其实 Controller 层是非常难于测试的,如果我们能够将 Controller 瘦身,就可以更方便地写 Unit Test 来测试各种与界面的无关的逻辑。移动端自动化测试框架都不太成熟,但是将 Controller 的代码抽取出来,是有助于我们做测试工作的。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-09-28,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 HelloWorld杰少 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
MVC、MVP、MVVM 架构的特点与区别
   前人种树,后人乘凉。关于MVC、MVP、MVVM这几种架构方式的理解,前辈们写了很多的解答,我结合几篇好文,总结了以下一点点内容。
老猫-Leo
2023/12/11
1.1K0
MVC、MVP、MVVM 架构的特点与区别
正确认识 MVC/MVP/MVVM
做移动端开发和前端开发的人员,对 MVC、MVP、MVVM 这几个名词应该都不陌生,这是三个最常用的应用架构模式,目的都是为了将业务和视图的实现代码分离,从而使同一个程序可以使用不同的表现形式。不过,网上的文章对这方面的解说众说纷纭,其中不乏有些错误的描述,导致有些人应用这些架构模式时陷入一些错误陷阱。本文将追根溯源,力求让大伙对这三个架构模式形成正确认识。
Keegan小钢
2020/12/11
3K1
正确认识 MVC/MVP/MVVM
理解mvvm和mvc
MVC 是一种使用 MVC(Model View Controller 模型-视图-控制器)设计创建 Web 应用程序的模式。 代表框架:AngularJS <br/>
心念
2023/01/11
8000
iOS面试题:MVVM和MVC的区别
你可能试着把它放在Model对象里,但是也会很棘手,因为网络调用应该使用异步,这样如果一个网络请求比持有它的model生命周期更长,事情将变的复杂。显然View里面做网络请求那就更格格不入了,因此只剩下Controller了。若这样,这又加剧了Massive View Controller的问题。若不这样,何处才是网络逻辑的家呢?
猿_人类
2019/07/04
1.5K0
iOS面试题:MVVM和MVC的区别
MVP/MVC/MVVM
View:它是提供给用户的操作界面,是程序的外壳; Model:是程序需要操作的数据和信息; Controller:接收View层传递过来的指令,选取Model层对应的数据,进行相应操作。
刘亦枫
2020/03/19
5280
MVP/MVC/MVVM
MVC、MVP、MVVM的理解与使用
对于MVC、MVP、MVVM,这都是Android开发的一种架构,随着日积月累的开发,很对人对这几种模式是再熟悉不过了。不过当初我在学习的时候是因为看一个开源项目的源码是MVP架构的,也找个很多文章,发现很多文章不是全是概念,就是解释的含糊不清,所以写一篇文章来分享,让像我一样的小白可以快速理解这几种架构模式。
g小志
2018/09/11
7830
MVC、MVP、MVVM的理解与使用
Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
MVC 初步解决了 Activity 代码太多的问题,但也有缺点:我们的初衷 Activity / Fragment 是只处理表现逻辑的部分 ,但现实是 Activity 天然不可避免要处理 UI,也要处理用户交互,说明 Activity 本身天然承担了 View 的角色。那么这个架构就会造成 Activity 里糅合了视图和业务的代码,分离程度不够。
用户9995743
2022/09/26
1.8K0
Android UI 架构演进:从 MVC 到 MVP、MVVM、MVI
MVC、MVP、MVVM三剑客
概述 说到Android MVVM,相信大家都会想到Google 2015年推出的DataBinding框架。然而两者的概念是不一样的,不能混为一谈。MVVM是一种架构模式,而DataBinding是一个实现数据和UI绑定的框架,是构建MVVM模式的一个工具。 之前看过很多的文章都有简单的介绍MVVM架构如何使用的,但是呢自己总是一知半解的状态,今天通过再次的学习,终于对MVVM有了一个更深刻的理解,现在就来分享下自己的心得。 MVC、MVP、MVVM 首先让我们来了解下Android中常见的开发模式。 M
用户1337002
2018/03/09
1.2K0
MVC、MVP、MVVM三剑客
聊聊iOS中的 MVC、MVP、MVVM以及 VIPER等代码组织方式
但是现实中我们的View依然跟Model耦合,因为如果完全按照这个理想化的MVC的话,View(cell)层的设置都应该在 Controller中,这样的话,Controller会更臃肿。
進无尽
2018/09/12
4.4K0
聊聊iOS中的 MVC、MVP、MVVM以及 VIPER等代码组织方式
了解一下MVC
一直在说MVC和MVVM的区别,现实是连什么是MVC都不知道,于是好好学习了一下MVC。
wade
2020/04/24
4610
了解一下MVC
技术趋势:是什么让MVC悄然消失的?
MVC这门技术伴随着我的成长,感情和Java一样深厚,但是,最近两年却不得不和MVC说再见了。是的,不是Struts没了,也不是SpringMVC没了,而是MVC这种架构模式被淘汰了。当时代抛弃你时,连一声再见都不会说。所以,看到这篇文章的各位程序员兄弟们,紧跟技术发展趋势,再牛逼一点的,能够提前预见技术趋势,提前准备,最牛逼的,引领技术趋势,咳咳,想的有点多。
码农编程进阶笔记
2021/07/20
9660
用代码手把手教你使用MVVM
网上关于MVVM框架的搭建和使用的文章很少,大多提到MVVM框架,就是在介绍DataBinding的使用。对于MVVM中各模块之间如何划分,如何定义,又是如何配合实现高度解耦的文章更是少之又少。大家看完后还是一头雾水,只是对MVVM有个大概的了解,并不很清楚如何上手。
蜻蜓队长
2018/08/03
2K0
用代码手把手教你使用MVVM
唯一可行的 iOS 架构
难道这是另一篇烦人的博客文章,模仿了 MVC 并提供了一种替代的“super-duper pattern”,而实际上只留下了更多的问题?这就是我看到另一篇有关 iOS 架构的文章时的想法。MVC,MVP,VIPER,RIBLET,Clean Swift等。这样的文章有很多,它们的观点和架构截然不同。
用户2932962
2020/02/25
1.4K0
iOS架构设计:揭秘MVC, MVP, MVVM以及VIPER
你将了解到在iOS环境下如何进行系统架构设计。我们将简单回顾一些流行的框架,并通过实践一些小例子来比较它们的理论。
iOSSir
2023/03/19
1.5K0
iOS架构设计:揭秘MVC, MVP, MVVM以及VIPER
聊聊iOS开发之MVVM的架构设计
而MVVM这种新的代码组织方式就可以解决这些问题,本文就MVVM的架构设计做个简单的个人总结。
進无尽
2018/09/12
8.9K0
聊聊iOS开发之MVVM的架构设计
PureMVC--一款多平台MVC框架
了解设计模式的人应该都多少听说过MVC模式。 严格意义上来说,“MVC模式”是一个伪概念,因为MVC并不属于设计模式,至少不属于GoF的23种设计模式之一,而更像是一个设计模式的结合体:V和C之间会实现观察者模式,M内部会实现单例模式,C在派发任务时会实现Command模式。 不得不说,MVC模式对软件的高可扩展性和高可维护性做出了巨大的贡献,这也使得MVC模式成为很多中等规模甚至大规模软件的常用框架,且经历了20余年仍旧在软件开发领域流行并通用,足可见MVC模式的经典。 但是传统MVC模式真的那么完美吗?
nimomeng
2018/09/13
1.7K0
PureMVC--一款多平台MVC框架
一文搞懂MVC、MVP、MVVM架构模式
架构(Architecture),又名软件架构,是有关软件整体结构与组件的抽象描述,用于指导大型软件系统各个方面的设计。常见的架构,如C/S架构,B/S架构等。
闫同学
2023/12/04
2.6K0
被误解的 MVC 和被神化的 MVVM(二)
image.png MVVM 的历史  MVVM 是 Model-View-ViewModel 的简写。相对于 MVC 的历史来说,MVVM 是一个相当新的架构,MVVM 最早于 2005 年被微软的 WPF 和 Silverlight 的架构师 John Gossman 提出,并且应用在微软的软件开发中。当时 MVC 已经被提出了 20 多年了,可见两者出现的年代差别有多大。 MVVM 在使用当中,通常还会利用双向绑定技术,使得 Model 变化时,ViewModel 会自动更新,而 ViewModel
HelloWorld杰少
2022/08/03
3740
被误解的 MVC 和被神化的 MVVM(二)
设计模式 | MVC、MVP、MVVM详析
MVC优缺点 【缺点】MVC的耦合性还是相对较高, View可以直接访问Model,导致3者之间构成回路。 因此, 【MVP与MVC的主要区别】是, MVP中的View不能直接访问Model, 需要通过Presenter发出请求,View与Model不直接通信。 另外, 耦合性高的MVC,相对于MVP、MVVM, 可读性、健壮性、可拓展性都大打折扣,也不便于测试; 【MVC缺点的对立面,就是MVP、MVVM的优点】 【优点】简单粗暴,适合简单项目 MVP优缺点 【缺点】对于简单的应用来说
凌川江雪
2020/04/14
3.4K0
设计模式 | MVC、MVP、MVVM详析
论MVVM伪框架结构和MVC中M的实现机制
一直都有人撰文吹捧MVVM应用开发框架,文章把MVVM说的天花乱坠并且批评包括iOS和android所用的MVC经典框架。这篇文章就是想给那些捧臭脚的人们泼泼冷水,虽然有可能招致骂声一片,但是目的是给那些刚入门的小伙伴一些参考和建议,以免误入歧途。同时也给那些深陷其中不能自拔的小伙伴们敲敲警钟,以免其在错误的道路上越走越远。
欧阳大哥2013
2018/08/22
8310
论MVVM伪框架结构和MVC中M的实现机制
相关推荐
MVC、MVP、MVVM 架构的特点与区别
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档