关闭

我与MVVM的恩怨情仇

标签: MVVMiOS架构
256人阅读 评论(0) 收藏 举报
分类:

记得面试那会儿,因为有一点MVVM的使用经验,跟面试官谈了一下。我的观点是,ViewModel封装展示逻辑,不包含接口调用,接口调用封装在另一个类里面(比如xxx API),然后在controller调用API类拿到数据后由ViewModel封装好给到视图层。当时得到的评价是,这不算是MVVM,还是在对Controller瘦身的层次上。

来到公司后发现,这里的MVVM是在ViewModel里包含了网络调用,读写缓存,业务逻辑,展示逻辑等等,几乎是Controller里面抽取了UIView,剩下的所有逻辑的集合。特意搜索了一些iOS MVVM的文章,的确是把众多逻辑都放在ViewModel里。但是一直觉得这种做法只是把臃肿从Controller移到了ViewModel,而且明显违背单一职责原则,ViewModel变成一个大杂烩。

今天看到一篇文章,MVVM 不是那么好,观点大致是:ViewModel引入太多的逻辑,MVVM只是转移和缓解了MVC的问题,无法彻底解决。讨论MVVP的文章看了不少,其中不乏抨击MVVM的,但这篇直入我心扉,也给了我不少启发。忍不住吐槽一下现在项目的MVVM。

现在的MVVM有什么问题?

  1. ViewModel职责太多。号称MVVM分离了UI和逻辑,但一个应用只分离UI和逻辑是远远不够的,”逻辑”里往往会有很多”子逻辑”,这里子逻辑现在全部堆在ViewModel里,造成了一个万能的ViewModel。导致一个ViewModel可能有非常多的状态和接口,迟早变成变成Massive ViewModel,重蹈Controller的覆辙。
  2. MVVM试图把UIViewController跟UIView看成同一个东西。Controller知道所有的View,它能响应整个页面视图的事件,在视图响应链里扮演重要角色,Controller有生命周期函数,业务层的调用入口往往是在这里。这些特性使Controller理所当然地充当胶水代码。这些特性即无法转移,也是独一无二的。所以Controller注定跟UIView不一样。即便在MVVM中Controller也负责ViewModel的生命周期管理。所以想把胶水抽到ViewModel中,把Controller薄化成UIView往往是不彻底的。
  3. 难以测试。最近在部门在推单元测试,由于之前有一些单元测试经验,毛遂自荐做了一次推动者。发现有些ViewModel测试无从下手,原因是状态复杂,内部逻辑太多。现在定义的ViewModel是封装逻辑提供给Controller使用,天生会积极隐藏Controller用不到的逻辑。按照测试原则,只测公有方法,但是内部又有一堆关键的逻辑。

他山之石,可以攻玉,看看其它语言和框架的MVVM是怎样的。

AngularJS 2.0版本听说大变样了,这里只说2.0以前的版本。AngularJS的MVVM跟iOS传统的MVVM大不一样,网络调用往往是封装在一个Service里面,并不包含在ViewModel,ViewModel($scope)非常薄,主要用来做数据绑定和事件转发。用AngularJS的经验不多,但是在一两个项目实践中,感觉AngularJS的MVVM比iOS传统的MVVM划分更合理一些。

那么,MVVM究竟该怎么玩?我的答案是:不必拘泥于既有的模式。

记得某大神说过,架构就是不停地拆分。拿到需求后,拆分成各个子功能,对应App各个子模块,然后子模块再细分,接着整理依赖关系,上浮下沉,自然就形成了分层。所以设计最关键的,不是拘泥于应用MVC或者MVVM或者MVP,而是学会拆分,把职责分离,形成高内聚的模块,并设计松耦合的接口。其中的利器便是SOLID原则,个人最常考虑的是S(单一职责)O(开闭原则),能把这两点做好,已经很可贵,正在努力攻关中。。。

重新思考了一下App架构大致的模样,细化后的模块,大致都可以被划分成几种类型,比如很多功能都需要一个网络请求的子模块,一个加工数据的模块。总结了一下,大致会有以下几种:API,Store,LogicModel,ViewModel,Controller,View。API封装网络,Store封装本地持久化,LogicModel封装业务逻辑(内存操作,跟后端架构中的领域层类似),ViewModel封装展示逻辑,Controller的职责还是胶水,它可能会持有各种对象,并负责协助对象通信。这些应该是大多数功能模块划分时都需要考虑的子模块。至于这么划分后还是MVVM吗?不要再思考这个问题,程序设计是一个创造性的活动,就像招术不是武术的根本,MVVM,MVP,MVC也不是设计的根本,设计原则才是。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:382次
    • 积分:12
    • 等级:
    • 排名:千里之外
    • 原创:1篇
    • 转载:0篇
    • 译文:0篇
    • 评论:0条
    文章分类
    文章存档
    阅读排行
    评论排行