我写过很多有关于让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 中呢?没人知道! 随便写就是了。

我们来看一些例子

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没你想象的那么的好的更多相关文章

  1. 全站 HTTPS 没你想象的那么简单

    对自己无知这件事本身的无知真的挺可怕 认知偏差现象一直存在于我们每个人身上,谁也避免不掉,不过是有的人了解这件事儿,有的人不怎么知道而已,这就产生了「无知而不自知」的认知偏差.当然,这时候你自己忽悠自 ...

  2. Fragment中监听onKey事件,没你想象的那么难。

    项目中越来越多的用到Fragment,在用Fragment取代TabHost的时候遇到了一个问题,我们都知道,TabHost的Tab为Activity实例,有OnKey事件,但是Fragment中没有 ...

  3. Don't Panic! KRACK 没你想象的那么糟

    上海交通大学密码与计算机安全实验室(LoCCS)软件安全小组(GoSSIP)版权所有,转载请与作者取得联系! 著名的计算机学术安全会议CCS在2017年录用了一篇名为Key Reinstallatio ...

  4. "简单"的优化--希尔排序也没你想象中那么难

    写在前边 大家好,我是melo,一名大二上软件工程在读生,经历了一年的摸滚,现在已经在工作室里边准备开发后台项目啦. 不过这篇文章呢,还是想跟大家聊一聊数据结构与算法,学校也是大二上才开设了数据结构这 ...

  5. mvvm小论(暂记)

    广州-PC26(34627) 2:09:44 在android 线程最后用 handler = new Handler();            updateThread = new Runnabl ...

  6. DOMO1

    以下是Demo首页的预览图 demo下载:http://www.eoeandroid.com/forum.php?mod=attachment&aid=NjE0Njh8ZTIyZDA2M2N8 ...

  7. Objective-C中的Block(闭包)

    学习OC有接触到一个新词Block(个人感觉又是一个牛气冲天的词),但不是新的概念,不是新的东西.学过Javascript的小伙伴对闭包应该不陌生吧~学过PHP的应该也不陌生,在PHP5.3版本以后也 ...

  8. 自己实现苹果安装app动画

    最近在学习CALayer相关动画,然后某一天突然发现苹果安装app这动画就很不错啊,所以就想自己实现下. 具体效果如图: 还是不试不知道一试吓一跳啊,这看上去简单的动画没我想象的那么简单. 首先这个动 ...

  9. Javascript:一个屌丝的逆袭

    HTML负责结构, CSS负责展示, 而我(加上AJAX, JSON) 负责逻辑.于是前端编程三剑客形成了. http://mp.weixin.qq.com/s?__biz=MzAxOTc0NzExN ...

随机推荐

  1. BZOJ3895 rock

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3895 看这题感觉好神. SG函数,dp....好像都不行呀. 最后去膜拜题解发现记忆化搜索 囧 ...

  2. 洛谷 - P1443 - 马的遍历 - bfs

    略有收获的bfs,使用了try_enqueue函数使得加入队列非常方便.性能理论上是一样的因为是inline? 还有就是左对齐是使用%-4d,相对于右对齐的%4d,还有右对齐前导零的%04d,自己试一 ...

  3. 了解Web Uploader

    1.简介WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件.在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流 ...

  4. 洛谷P4199 万径人踪灭(manacher+FFT)

    传送门 题目所求为所有的不连续回文子序列个数,可以转化为回文子序列数-回文子串数 回文子串manacher跑一跑就行了,考虑怎么求回文子序列数 我们考虑,如果$S_i$是回文子序列的对称中心,那么只要 ...

  5. 项目中java异常处理

    一.java异常类介绍. Throwable: 有两个重要的子类:Exception(异常)和 Error(错误),二者都是 Java 异常处理的重要子类,各自都包含大量子类. 有一篇比较好的blog ...

  6. 使用Spring MVC的@RequestBody注解接收Json对象字符串

    最近公司在开发移动APP,APP上通过jQuery提交表单的json字符串格式数据到Java后端,之前通过request手动接收,非常麻烦,其实Spring MVC已经为我们提供了一个注解@Reque ...

  7. python之商品操作小程序

    要求:写一个添加商品的程序,商品信息写入txt文件中,以二维字典形式比如:{‘小米’:{‘价格’:‘1999元’,‘数量’:10}} 1.添加商品 #商品名称 #价格 #数量 2.查看商品 3.删除商 ...

  8. D Tree HDU - 4812

    https://vjudge.net/problem/HDU-4812 点分就没一道不卡常的? 卡常记录: 1.求逆元忘开longlong 2.把solve中分离各个子树的方法,由“一开始全部加入,处 ...

  9. PWA之push服务

    转载: https://www.jishux.com/p/c5735af96c39bd4a https://www.jianshu.com/p/9970a9340a2d 系列文章参考:https:// ...

  10. 当css样式表遇到层2

    9.定制层的display属性:层的表现是通过框这种结构来实现的.框可以是块级对象也可以是行内对象. Display属性就是用来控制其中内容是块级还是行级.定义为block则为kuai块级,inlin ...