MVVM没你想象的那么的好
我写过很多有关于让View Controller 更易于理解的文章,其中一种比较常见的模式就是Model-View-ViewModel(MVVM)。 我认为MVVM 是一种非常容易让人混淆的 anti-pattern(反面模式设计)。View models是很糟糕的名字,它只是优秀架构之路上的权宜之计。我们的团体将从这种模式过度到更好的模式。
MVVM 是一个很糟糕的名字
名字很重要。理想的情况下,一个名字能够有效地表达这个对象是什么,它扮演了什么样的角色,以及如何使用它等。View model作为一个名字,没有起到任何的作用。
以我的经验来看,考虑到view model的抽象性,它实际上代表了两种迥然不同的模式
第一种 “view model” 是 “model for the view”。这是一个dumb object(在Swift中绝对是一个结构体) 用来传递 view 给它的子视图。它不应该包含任何逻辑甚至是任何方法。这跟UILabel包含string,或者UIImageView包含Image,自定义profileView包含profileViewModel 是一样的道理。它直接传递给你的ProfileView,最重要的是,它允许你将子视图私有化,而不是将子视图暴露在外面。这是一个非常好的方法。我见过一种叫 view data 的模式,我非常喜欢这种模式,因为它将自己从定义模糊不清的”view model” 中剥离出来了。
View model 同时也一种介于model object和view controller之间模糊的、抽象的名词。它处理数据展示、网络请求获取数据、表单验证和你认为可以放在这里的其他任务。这种万金油风格的对象主要用来减轻控制器的压力。但是最终,你只是多建立了一个能够让你将任务分工倒进去的容器。
MVVM 承担了更多的责任
这种缺乏具体内涵的名字导致了这个类负责的东西无限地增长。那么什么样的功能才应该放在 view model 中呢?没人知道! 随便写就是了。
我们来看一些例子
- Let’s discuss MVVM for iOS 这篇文章展示了view model 中的网络数据模型 ,推荐你在里边添加验证和展示逻辑。
- Introduction to MVVM 这篇文章展示了如何将表示逻辑放入视图模型中,同时引发了一个问题–为什么它不叫 Presenter?
- COCOA SAMURAI?这篇告诉你应该用view model来上传数据并绑定ReactiveCocoa.
- ReactiveCocoa and MVVM, an Introduction 这篇使用view model 来表格验证和获取数据。
- Model-View-ViewModel for iOS 这篇文章特别建议你将“miscellaneous code”(“无法明确定义的代码”) 放入到view model 中。
View Model非常适用于存放用户输入的验证逻辑,视图的表示逻辑, 网络请求的初始化和其它“miscellaneous code ”的地方。
没人知道“view model”代表着什么,所以人们无法在view model 应该包含什么内容这一问题上达成一致。view model 这个概念本身就太抽象了。这些作者在Validator class、Presenter class 或者 Fetcher class 该做哪些事和不该做哪些事上有不同的观点。这些都是有着明确定义的好名字。
假设一个同样的名字,在不同的对象中有着迥然不同的任务分工,那么它只会混淆读代码的人。如果我们无法在view model 的作用上达成一致,那么将这些不同作用的“view model”取成同一个名字又由什么好处呢?
我们已知的规律中已经面临了一个同样的挑战,并且我们发现“controller”的名字定义太广泛了,它能够包含很多小的任务 .
你完全可以给你自己的类定义一个你想要的名字!选一个好点的名字
MVVM并没有改变你代码的结构
最后,view models 本质上并没有改变你app的结构。这两幅图有什么区别?(source)

你不需要高级的图形理论就可以看出他们基本上是完全一样的。
我所知道这个模式最清楚的地方就是: 它将view controller 中的(view controller不是一个你拥有的对象,因为它是Apple class 的一个子类) 代码移动到了你拥有的view model 中。这样view controller 就很容易的能够聚焦view生命周期时间。尽管这样,我们的代码还是大量的聚集在一起,它只是从view controller 移动到了 view model 中而已。
因为view model 只有一个,我们还没有解决这个复杂的问题。如果你创建一个view model 来避免你的控制器过于臃肿,那么如果你的app代码又增加了一倍要怎么办?或许到那时候,我们可以加一个controller-model.
这种view model 解决方法不是很好,它只是在问题上贴了一个创可贴,问题还会继续出现。我们需要一个更好的,能从根本上解决问题的办法。就像一个能够在对象变得更大时,你能够对其进行持续性的划分,好比正在进行有丝分裂的细胞。view model它只是个一次性的补丁。
其他的团体已经经历过这样的问题
Rails community 在几年前就经历过这个问题,我们能够从他们的故事中有所借鉴。首先,他们controller非常臃肿 ,除了persistence(持久性数据)外,几乎是一个空的模型。这样的代码几乎无法测试,于是他们将所有的逻辑移动到了model中,这样就有了简洁的controller和臃肿的model。由于臃肿的model依靠于ActiveRecord, 这样的话数据库依旧很难测试并且需要拆分成很小的单元。
博客里面已经贴出了像 7 Patterns to Refactor Fat ActiveRecord Models这篇文章 (给了我写8 Patterns to Help You Destroy Massive View Controller这篇文章的灵感),这是上述思维方式的产品例子。最终,你将持续将你的核心分割成小的单元,那么移动你的代码时就能够有效的划分到对应的区域。
View model作为一种解决方法,并不适用于现代编程模式的变化。他们是一种定义不清的结构,不知道应该包含什么,这就导致了它们会遇到和view controller 一样的问题。它们只是当我们遇到复杂问题的临时补丁,如果我们忽略这些问题,在不久之后问题再次出现时,我们还是要解决同样的问题。
http://ios.jobbole.com/83759/
MVVM没你想象的那么的好的更多相关文章
- 全站 HTTPS 没你想象的那么简单
对自己无知这件事本身的无知真的挺可怕 认知偏差现象一直存在于我们每个人身上,谁也避免不掉,不过是有的人了解这件事儿,有的人不怎么知道而已,这就产生了「无知而不自知」的认知偏差.当然,这时候你自己忽悠自 ...
- Fragment中监听onKey事件,没你想象的那么难。
项目中越来越多的用到Fragment,在用Fragment取代TabHost的时候遇到了一个问题,我们都知道,TabHost的Tab为Activity实例,有OnKey事件,但是Fragment中没有 ...
- Don't Panic! KRACK 没你想象的那么糟
上海交通大学密码与计算机安全实验室(LoCCS)软件安全小组(GoSSIP)版权所有,转载请与作者取得联系! 著名的计算机学术安全会议CCS在2017年录用了一篇名为Key Reinstallatio ...
- "简单"的优化--希尔排序也没你想象中那么难
写在前边 大家好,我是melo,一名大二上软件工程在读生,经历了一年的摸滚,现在已经在工作室里边准备开发后台项目啦. 不过这篇文章呢,还是想跟大家聊一聊数据结构与算法,学校也是大二上才开设了数据结构这 ...
- mvvm小论(暂记)
广州-PC26(34627) 2:09:44 在android 线程最后用 handler = new Handler(); updateThread = new Runnabl ...
- DOMO1
以下是Demo首页的预览图 demo下载:http://www.eoeandroid.com/forum.php?mod=attachment&aid=NjE0Njh8ZTIyZDA2M2N8 ...
- Objective-C中的Block(闭包)
学习OC有接触到一个新词Block(个人感觉又是一个牛气冲天的词),但不是新的概念,不是新的东西.学过Javascript的小伙伴对闭包应该不陌生吧~学过PHP的应该也不陌生,在PHP5.3版本以后也 ...
- 自己实现苹果安装app动画
最近在学习CALayer相关动画,然后某一天突然发现苹果安装app这动画就很不错啊,所以就想自己实现下. 具体效果如图: 还是不试不知道一试吓一跳啊,这看上去简单的动画没我想象的那么简单. 首先这个动 ...
- Javascript:一个屌丝的逆袭
HTML负责结构, CSS负责展示, 而我(加上AJAX, JSON) 负责逻辑.于是前端编程三剑客形成了. http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExN ...
随机推荐
- I.MX6 boot from Micro SD
/***************************************************************************** * I.MX6 boot from Mic ...
- Name That Number
链接 分析:找出每一个字母对应的数字,然后看字典里面那个与其匹配 /* ID: **** PROG: namenum LANG: C++ */ #include<iostream> #in ...
- MFC程序中的 _T("") 什么意思?
_T("")就是把引号内的字符串转换为宽字节的Unicode编码 宽字节就是unicode.
- Hibernate 4.3 配置文件实现
1.建立web项目 2.复制相关的jar文件到 项目的lib目录下antlr-2.7.7.jardom4j-1.6.1.jarhibernate-commons-annotations-4.0.5.F ...
- ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 16. 角色管理
注入UserManager和RoleManager 建立View页面.这段视频中没有录. RoleManager的服务没有注册 注册的地方进行修改 再次运行就可以了 这个ViewModel实际上只需要 ...
- 2019年5月22日 AY 程序员调侃语录
我是AY,杨洋,做wpf开发的,最近得了一种病,程序员患得患失综合征.同事说,我年纪在变大,技术跟不上.业余之间,我原创了写了一些语录,给大家中午休息,累疲惫的时候,开心放松下. 1.活着的每一天都无 ...
- 洛谷P4725 【模板】多项式对数函数(多项式运算)
传送门 前置芝士:微积分(有所了解即可)(可以看看这篇,写得非常详细我看了两章就看不下去了) 以下都是一些简单的教程切莫当真,仅供理解,建议看更严谨的 导数:对于一个函数$f(x)$,它的导数$f'( ...
- bzoj4472: [Jsoi2015]salesman(树形dp)
Description 某售货员小T要到若干城镇去推销商品,由于该地区是交通不便的山区,任意两个城镇之间都只有唯一的可能经过其它城镇的路线. 小T 可以准确地估计出在每个城镇停留的净收益.这些净收益可 ...
- CF580D Kefa and Dishes 【状压dp】By cellur925
题目传送门 友情链接:new2zydalao%%% 一篇优秀的状压文章 题目大意:$n$个菜有$k$个规则,如果kefa在吃完第$xi$个菜之后吃了第$yi$个菜(保证$xi$.$yi$不相等), ...
- jQuery笔记之工具方法—高级方法Ajax
$.ajxa() ——基本使用 前提:先了解js的执行机制 $.Callbacks()——回调 $.Deferred()——异步 $.when() 网络服务器链接由<渡一教育>提供 --- ...