我写过很多有关于让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. 【CQ18阶梯赛第二场】题解

    [A-H国的身份证号码I] 用N个for语句可以搞定,但是写起来不方便,所以搜索. dfs(w,num,p)表示搜索完前w位,前面x组成的数位num,最后以为为p. 如果搜索到第N位,则表示num满足 ...

  2. javaScript的几个问题简答

    1.javascript的typeof返回哪些数据类型    Object.number. function. boolean. underfind 2.例举3种强制类型转换和2种隐式类型转换?    ...

  3. Centos7 编译安装 Nginx、MariaDB、PHP

    前言 本文主要大致介绍CentOS 7下编译安装Nginx.MariaDB.PHP.面向有Linux基础且爱好钻研的朋友.技艺不精,疏漏再所难免,还望指正. 环境简介: 系统: CentOS 7,最小 ...

  4. C:根据日期判断是一年的第几天、星期几

    W = [Y-1] + [(Y-1)/4] - [(Y-1)/100] + [(Y-1)/400] + D Y是年份数,D是这一天在这一年中的累积天数,也就是这一天在这一年中是第几天. 最好用的是蔡勒 ...

  5. linux以行为单位进行读写操作

    1 gets/fgets函数 char* fgets(char *restrict buf,int n,FILE *restrict fp) 参数1:存放读入串的缓冲区 参数2:表示读入的字符个数,最 ...

  6. 任务24:WebHost的配置

    24 任务24:WebHost的配置 创建HelloCore的项目 我们新建一个空的mvc项目 我们在这里调用COnfigureAppConfiguration方法更改默认的配置.为读取setting ...

  7. input required字段;django input输入框不填写会自动变红如何修改

    前端页面中,input不输入任何内容时,点击submit时,未填写的input会标红框,有些人还会有"该字段必填的字样"!! 什么鬼,你妹的,js也见不到,css3动画也见不到,怎 ...

  8. 洛谷 - P1403 - 约数研究 - 数论

    https://www.luogu.org/problemnew/show/P1403 可以直接用线性筛约数个数求出来,但实际上n以内i的倍数的个数为n/i的下整,要求的其实是 $$\sum\limi ...

  9. 高级开发不得不懂的Redis Cluster数据分片机制

    Redis 集群简介 Redis Cluster 是 Redis 的分布式解决方案,在 3.0 版本正式推出,有效地解决了 Redis 分布式方面的需求. Redis Cluster 一般由多个节点组 ...

  10. Fiddler 学习

    Little Skill Fiddler 官网: https://www.telerik.com/fiddler 来自 https://www.cnblogs.com/zhaoyanjun/p/706 ...