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 · Mar 24, 2016 · 6695 views
    This topic created in 3786 days ago, the information mentioned may be changed or developed.

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

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

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

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

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

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

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

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

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

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

    kitalphaj
        33
    kitalphaj  
       Apr 5, 2016
    看了半天没看懂,明明是在说 MVVM ,全都扯到 React 上去了。。。就算这俩经常一起用也不能混为一谈啊。单独用 React 完全没有问题,而且现在用了 Swift 的面向协议的编程后,完全可以把很多显示逻辑放到 extension 里面。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2679 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 56ms · UTC 15:48 · PVG 23:48 · LAX 08:48 · JFK 11:48
    ♥ Do have faith in what you're doing.