V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
iOS 开发实用技术导航
NSHipster 中文版
http://nshipster.cn/
cocos2d 开源 2D 游戏引擎
http://www.cocos2d-iphone.org/
CocoaPods
http://cocoapods.org/
Google Analytics for Mobile 统计解决方案
http://code.google.com/mobile/analytics/
WWDC
https://developer.apple.com/wwdc/
Design Guides and Resources
https://developer.apple.com/design/
Transcripts of WWDC sessions
http://asciiwwdc.com
Cocoa with Love
http://cocoawithlove.com/
Cocoa Dev Central
http://cocoadevcentral.com/
NSHipster
http://nshipster.com/
Style Guides
Google Objective-C Style Guide
NYTimes Objective-C Style Guide
Useful Tools and Services
Charles Web Debugging Proxy
Smore
hampotato
V2EX  ›  iDev

真的有必要用 MVVM 吗?

  •  
  •   hampotato · 2016-03-24 11:21:33 +08:00 · 6003 次点击
    这是一个创建于 3173 天前的主题,其中的信息可能已经有所发展或是发生改变。

    先道歉,可能有点标题党了。很早就看到过 MVVM 这个架构,一直没在工程里用过,但看到描述它的文章真是非常多。然而很想问:什么情况下适合用 MVVM ?一般比较常规的 app 真的需要用 MVVM 吗?

    就从 objc 的这篇文章 来看,mvvm 大概有 3 个优点:

    1. 业务逻辑可以放到 viewModel 层
    2. 便于测试
    3. 视图与数据绑定,数据更新的时候,视图可以自动更新(如果用 ReactCocoa 之类 KVC 绑定的话)。

    我想一条一条地来看:

    1. 业务逻辑可以放到 viewModel 层

      我就想问,到底能有多少业务逻辑呀?像上面文章的举例,我们完全可以在 Person 类添加一个-(NSString*)nameDescription方法,一个-(NSString*)birthdayText方法。像这种拼一拼字符串的逻辑,放在 model 层是不是就足以解决问题了。

      我想如果真是复杂的计算,也不适合在 app 端做;一般服务器都是把数据处理好, app 只要直接显示出来就行了。如果真是图片处理、视频合成这种的,也应该单独写个 service 类,本来也不该放在 viewController 里。这里所说的『业务逻辑』,我只能想到拼一拼字符串, timestamp 转成格式化时间等,这些东西真的有必要挪出来专门弄一个类吗。

      我看到 viewController 大坨的代码,主要有就是 cell 和行高的路由分发和各种事件响应,我想 MVVM 并不能让它瘦身吧。

    2. 便于测试

      这点很有道理,不过假如上面一点成立的话,光测这点简单逻辑也没大用,毕竟这些东西不容易错,不容易被不慎改坏,出 bug 也不容易出在这里。

    3. 数据更新的时候,视图可以自动更新

      好吧,也许是我太 low ,但我见过 80% 的 viewController 都是这样的:显示 loading -> 发网络请求 -> 数据回来了,[tableView reloadData];。这个『自动更新』也就是省了一句 [tableView reloadData]; 而已,这个有那么重要吗。

      比如更新视图一种比较麻烦的情况,比如用户从列表页进详情页,编辑了某种属性,回到列表页的时候要更新。然而 KVO 并不能解决这个问题啊。因为进到详情页,往往还需要再发网络请求,用户编辑属性的 model 跟列表里的已经不是一个对象了,也不会触发 KVO 。

    综合上面这几条,我并不能想出 MVVM 特别有用的情况。但是有很多人都说,用了 ReactCocoa 真爽,效率提高 100 倍,代码省了很多,等等。

    所以在此向大家请教,希望有朋友能给我一点提示,什么情况下用了 MVVM 确实有奇效。谢谢!

    33 条回复    2016-04-05 08:48:12 +08:00
    yuuko
        1
    yuuko  
       2016-03-24 11:30:57 +08:00
    有没有必要,看你有没有需求,没这个需求就没有必要,有这个需求就有必要
    v1024
        2
    v1024  
       2016-03-24 11:48:48 +08:00
    做 todo demo 很有用(手动斜眼
    holy_sin
        3
    holy_sin  
       2016-03-24 12:12:33 +08:00   ❤️ 1
    [[[[client
    logInUser]
    flattenMap:^(User *user) {
    // Return a signal that loads cached messages for the user.
    return [client loadCachedMessagesForUser:user];
    }]
    flattenMap:^(NSArray *messages) {
    // Return a signal that fetches any remaining messages.
    return [client fetchMessagesAfterMessage:messages.lastObject];
    }]
    subscribeNext:^(NSArray *newMessages) {
    NSLog(@"New messages: %@", newMessages);
    } completed:^{
    NSLog(@"Fetched all messages.");
    }];

    这个例子还比较经典,其实说到底就是封装吧
    xi_lin
        4
    xi_lin  
       2016-03-24 12:15:52 +08:00
    1. Model 和 ViewModel 是两回事。一个 ViewModel 可能涉及到多个 Model ,有些业务逻辑要跨 model 操作的,就可以放到 ViewModel 里。
    3. 你需要看的是双向绑定
    blacklee
        5
    blacklee  
       2016-03-24 12:27:46 +08:00 via iPhone
    RAC 确实很爽!非常爽!单独用就可以。
    MVVM 还没用,看文档感觉一般。
    对 View 的包装比较重要,尽量少让 View 的代码出现在 ViewController 里面。
    hampotato
        6
    hampotato  
    OP
       2016-03-24 12:32:08 +08:00
    @holy_sin 嗯嗯,看了下 RC 的这个例子,这样写确实不错~
    hampotato
        7
    hampotato  
    OP
       2016-03-24 12:33:00 +08:00
    @xi_lin 想问下一个 ViewModel 涉及到多个 Model 的时候,那这一个 ViewModel 对应一个 View 吗?
    otakustay
        8
    otakustay  
       2016-03-24 12:48:52 +08:00
    @hampotato ViewModel 都是对应 View 的,基本上倾向于基于 View 设计 ViewModel 的结构
    xi_lin
        9
    xi_lin  
       2016-03-24 12:58:33 +08:00
    @hampotato 看你的粒度划分吧,我自己的习惯是一个 ViewController 对应一个 ViewModel 。复杂界面另说。
    mko0okmko0
        10
    mko0okmko0  
       2016-03-24 13:02:39 +08:00
    没有瀑布流的时候不使用复杂的设计和实作.
    chaoxn
        11
    chaoxn  
       2016-03-24 13:44:00 +08:00
    MVVM 还是和 RAC 结合起来的时候爽,单独 MVVM 不是很有必要
    DingSoung
        12
    DingSoung  
       2016-03-24 13:52:17 +08:00
    现在经常用啊, 模块分开了, 对外逻辑简单了
    xhowhy
        13
    xhowhy  
       2016-03-24 13:55:43 +08:00
    MVVM 本质上不是什么创新的东西, React 的思路才是,加了层 Virtual DOM
    Wangxf
        14
    Wangxf  
       2016-03-24 13:56:23 +08:00   ❤️ 1
    看需求吧,我就问你一个问题,假如现在有两个 input[type="text"],两个框旁边有个 span 或者说没有容器,你想要让自己随便在哪个框里输入数字,那个容器里会得到两个数相加的结果,是你你会怎么做?对比下传统的方式和 mvvm 框架来处理的方式你会发现生产效率提高了一大半
    longaiwp
        15
    longaiwp  
       2016-03-24 14:45:31 +08:00
    @xhowhy 你这个想法,我只能说呵呵
    huanglexus
        16
    huanglexus  
       2016-03-24 14:56:45 +08:00
    @holy_sin 然而这个例子跟 mvvm 一点关系都没有,这就是个 monad 的应用,跟 promise 一模一样
    myrual
        17
    myrual  
       2016-03-24 15:04:20 +08:00
    说效率提高 100 倍是扯淡的。
    网络操作引发的 ui 更新方便是真的。
    hampotato
        18
    hampotato  
    OP
       2016-03-24 15:50:54 +08:00
    @Wangxf 有道理,有些输入验证的时候用得上。有点像 angular 的优势
    ChefIsAwesome
        19
    ChefIsAwesome  
       2016-03-24 16:24:36 +08:00   ❤️ 2
    典型的就是购物车, TODO list 那样的东西。要解决的就是这么一个问题:同一块数据出现在 view 里的不同地方,这些地方又都能修改这个数据,怎么让这些地方同步起来。简单讲就是 mvc ,你修改 modal , modal 触发 change 事件, view 注册这个事件,把 view 上面跟 modal 相关的地方都给更新了。 mvvm 是更新 view 的一种方法,前端的 react 用的是另外一种方法。不管你选 mvvm 还是其他什么,基本上你要做的都只是更新 modal ,其他的交给框架来做。
    wshcdr
        20
    wshcdr  
       2016-03-24 16:35:57 +08:00
    viewModel 放显示逻辑...
    hampotato
        21
    hampotato  
    OP
       2016-03-24 17:31:41 +08:00
    @ChefIsAwesome 明白了~~ 购物车这个例子很有说服力~ 谢谢~~
    hjc4869
        22
    hjc4869  
       2016-03-24 17:36:07 +08:00
    展示算法用的 demo app 不需要用 MVVM 。
    holy_sin
        23
    holy_sin  
       2016-03-24 18:13:10 +08:00
    @ChefIsAwesome 有道理,按我的理解可以概括为数据驱动 UI
    jesse_luo
        24
    jesse_luo  
       2016-03-24 23:42:34 +08:00
    我觉得是不是 MVVM 不重要,重要的是单向数据流(数据绑定)和逻辑拆分
    jesse_luo
        25
    jesse_luo  
       2016-03-24 23:44:49 +08:00
    @ChefIsAwesome 对的,只要操作要展示的数据,剩下的都由一个可靠的框架实现
    另外有的 VM 也会变得很大,所以横向拆分数据和逻辑也很重要
    xhowhy
        26
    xhowhy  
       2016-03-29 14:19:46 +08:00
    @longaiwp 就你呵呵,就你呱呱叫
    xhowhy
        27
    xhowhy  
       2016-03-29 14:25:21 +08:00
    @longaiwp http://www.infoq.com/cn/articles/rethinking-mvc-mvvm
    mvvm 微软早在 2005 年就推出了,又不是什么新奇东西,知道它为什么没火吗?除了微软本身生态不行之外, mvvm 只适合于简单的界面编程,因为:

    1. 对于大型的图形应用程序,视图状态较多, ViewModel 的构建和维护的成本都会比较高。
    2. 数据绑定的声明是指令式地写在 View 的模版当中的,这些内容是没办法去打断点 debug 的。

    这种创新没多大用,明显没有考虑到覆盖普适和复杂的业务场景,而反观单向数据流,设计上反而更先进一些。
    longaiwp
        28
    longaiwp  
       2016-03-29 16:40:01 +08:00
    @xhowhy 这东西没火只是你的一厢情愿吧,那么多基于 MVVM 思想构建的程序,第一点我赞同,状态过多维护成本会很高,但是可测试性好太多了还有耦合度也下降了,第二点,这类内容的 debug 需求不高,你为什么要确定绑定是否失败?当然这个问题本身存在。最后一句, MVVM 不是万能的东西,但是也没你讲的那么不堪,它自有它的优点,但是这个世界写代码没有银弹
    xhowhy
        29
    xhowhy  
       2016-03-29 17:08:45 +08:00
    @longaiwp 不能 debug 就是深坑啊,如果你写码过超过 3 年,我想你应该可以理解啊。 React 的 JSX 至少还是可以调试的,因为数据流有据可循,但 MVVM 的 View 发生变化你却找不出是哪里的 M 改动导致的。
    另外,如果 MVVM 是真火了,更早火起来的 Angular 为啥会被 React 后来追上?
    本质没有变,当然就不能真的火啦
    longaiwp
        30
    longaiwp  
       2016-03-30 07:50:26 +08:00
    @xhowhy 你说的是另外一回事了,当然这也是 Redux 的优点,那就是可预测性,当然也一定程度提升了代码的复杂度,当然对于大型的项目里,这种可预测性对于维护是很重要的。而且 Angular 和 React 比较起来, Angular 不是因为 MVVM 才被追上。不然我要问,为什么 React 会被 Vue 后来追上?
    xhowhy
        31
    xhowhy  
       2016-03-30 14:36:32 +08:00
    @longaiwp no no no ,没提到 redux ,我说的主要是 React 。。另外 Vue 是什么鬼
    zhigang1992
        32
    zhigang1992  
       2016-04-04 22:00:17 +08:00
    其实规模稍微大一点的应用还是有一堆一堆的业务逻辑的。

    服务器给出、接受的往往在设计上的时候考虑的是数据本身的属性,而不是按照界面、交互来设计的。

    而这里面的转化往往不仅仅是一个 Mapper 能搞定的。

    我个人的理解就是 ViewModel 其实算一个 View / Interaction 和 Model 之间的桥梁。

    这种情况下可测就非常重要, UIView, UIViewController 测试起来太恼火了。往往导致后面大家都不写这些逻辑的测试。

    ViewModel 应该于 UIKit 隔离开来,这样就又一个好处,

    在用 Xamarin 之类的东西做跨平台应用的时候,

    一套 ViewModel 可以给 iOS 和 Android 共享代码,只要在 View 层做不同的绑定和交互就可以。

    kitalphaj
        33
    kitalphaj  
       2016-04-05 08:48:12 +08:00
    看了半天没看懂,明明是在说 MVVM ,全都扯到 React 上去了。。。就算这俩经常一起用也不能混为一谈啊。单独用 React 完全没有问题,而且现在用了 Swift 的面向协议的编程后,完全可以把很多显示逻辑放到 extension 里面。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1104 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 23:40 · PVG 07:40 · LAX 15:40 · JFK 18:40
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.