凌云时刻

写在前面

讨论下一代开发模式的演化、优化方向和可能,不一定正确希望和感兴趣的读者交流。

任何模式的选择一定要根据当时的开发需要来决定。比如:实验性、迭代很快的简单需求,一般会先选择MVC尝试,待明确方向后,再考虑改为MVVM。

背景

首先,看下iOS首推的MVC模式。

  • M:单纯的从网络获取回来的数据模型

  • V:视图界面

  • C:ViewController

ViewController负责View和Model之间调度,View发生交互事件会通过target-action或者delegate方式回调给ViewController,与此同时ViewController还要承担把Model通过KVO、Notification方式传来的数据传输给View用于展示的责任。

随着业务越来越复杂,视图交互越复杂,导致Controller越来越臃肿,负重前行。福报修多了的结果就是,不行了就重构,重构不了就换掉。

为了解决MVC带来的问题,MVVM出现了。

把View和Controller都放在了View层(相当于把Controller一部分逻辑抽离了出来),Model层依然是服务端返回的数据模型。而ViewModel充当了一个UI适配器的角色,也就是说View中每个UI元素都应该在ViewModel找到与之对应的属性。除此之外,从Controller抽离出来的与UI有关的逻辑都放在了ViewModel中,这样就减轻了Controller的负担。

从以上的架构图中,我们可以很清晰的梳理出各自的分工。

  • View层:视图展示。包含UIView以及UIViewController,View层是可以持有ViewModel的。

  • ViewModel层:视图适配器。暴露属性与View元素显示内容或者元素状态一一对应。一般情况下ViewModel暴露的属性建议是readOnly的,还有一点,ViewModel层是可以持有Model的。

  • Model层:数据模型与持久化抽象模型。数据模型很好理解,就是从服务器拉回来的JSON数据。而持久化抽象模型暂时放在Model层,是因为MVVM诞生之初就没有对这块进行很细致的描述。按照经验,我们通常把数据库、文件操作封装成Model,并对外提供操作接口。(有些公司把数据存取操作单拎出来一层,称之为DataAdapter层,所以在业内会有很多MVVM的变种,但其本质上都是MVVM)。

  • Binder:MVVM的灵魂。可惜在MVVM这几个英文单词中并没有它的一席之地,它的最主要作用是在View和ViewModel之间做了双向数据绑定。如果MVVM没有Binder,那么它与MVC的差异不是很大。

需要注意一点,View持有ViewModel,ViewModel不能持有View(即ViewModel不能依赖UIKit中任何东西)。有两个原因:一是为了ViewModel可测性,即单元测试方便进行;二是团队人员可分离开发。可总结为:更加干净的解耦。

存在的问题

MVVM公认的问题

  • 学习成本高

  • 绑定数据比较繁琐,容易引起crash

  • 犹豫要不要引入RAC

问题1

任何新技术,新模式都是有学习成本,MVVM也不例外,但是并不是非常高,阅读相关文章,以及技术大咖做的demo,经过一两个需求就基本掌握了。

问题2

在不使用RAC的情况下,一般使用KVO、类KVO来解决,需要在初始时绑定,dealloc移除绑定,还要避免主动修改viewModel值造成UI的循环响应修改。的确,相对繁琐,但已经有其他开源方案可以解决,既方便,又安全。

问题3

(个人意见)如果非必需,建议不要引用RAC,有两个原因,一是因为RAC学习成本需要颠覆之前的开发方式;二是RAC对性能影响非常大,一个简单的数据响应也会生成非常多信号量。

问题不止这些

经过长时间的使用,发现MVVM的viewModel的确可以抽离V/VC中的业务逻辑,但是不同VM由于对外接口不统一,相似的业务,如果通过VM之间的继承,可以解决当时问题,但是随着迭代,判断逻辑越来越多;如果创建各自独立VM,部分能力又会重复造轮子。

例如,页面A某个功能需要,先判断登陆,再上传修改;页面B某个功能需要,先判断登陆,再查看信息。

方案一

viewModelB继承viewModelA,viewModelA声明一个nextActionAfterLoginCheck public方法。viewModelA登录判断后调用nextActionAfterLoginCheck,而viewModelB重写即可。

但后期需要页面A在登录增加封禁账号不能修改信息,那么页面A就不用调用nextActionAfterLoginCheck,但是页面B需要。这时可以再声明一个

-(bool)shouldToDoNextAction 方法,在登录判断后通过这个方法获取A、B各自返回值,决定是否调用nextActionAfterLoginCheck,既保证nextActionAfterLoginCheck业务独立性(不涉及账户相关判断),又保证继承关系不变。但是登录模块代码引入了新的判断,VM臃肿化前兆现象。

方案二

页面A、页面B各自拥有自己的viewModel,这样登录逻辑便重复,但是日后修改,两个页面独立,互不影响。

有没有更好的解决方案呢?

分析

对比一下前后功能

* 开始时,页面A、B所包含的功能:登录判断、上传修改、查看信息。

* 后期迭代,页面A增加:封禁用户判断。

表面上,造成VM臃肿隐患的原因,是既要保留公用登录模块的前提下,完成页面A新的业务需要,又要最小影响页面B,则需要增加判断完成。那进一步分析业务链路,发现最终的形态如下:

根本上,VM自身承担的业务定义、执行,造成了各个功能无法灵活组织,随时可变,每一个功能修改都有可能影响到其他业务。

解决方案

如果VM只承担业务定义呢?通俗一点的说法,V/VC告诉VM要做一个什么业务,VM定义这个业务需要哪几个功能,具体功能实现不在VM实现,那么VM在后期迭代中只需要更新定义即可,无非是增删改定义的几个功能而已。

用这个思路分析上面case,既然不用实现功能,那么viewModelB就不用继承viewModelB,两个页面独立,viewModelA业务定义:登录判断、封禁判断、上传修改,viewModelB业务定义:登录判断、查看信息。

如此分析,可以发现,每个功能都被拆分成了相对“干净”的最小功能,那么这些功能在哪里实现呢?暂且叫它业务中心(Service)吧,新MVVMS模型图如下:

技术调研

若要实现上面的方案,必须解决3个问题:

  • 如何定义

  • 结果如何返回

  • Service应该如何设计

需要一套语法解决定义

个人觉得VM最终目标只需要传入一串字符、参数,就能完成一个具体业务。那么定义了字符,就涉及到解析、翻译,借鉴编译原理,我们需要一套定义业务的语法。

将相对独立、闭环的功能,称为原子功能,每个原子功能为一个编码,相关功能为一个模块,一个模块为一个编码区。例如:账户为模块Account,则登录判断(Account01)、登录(Account02)、封禁判断(Account03);信息模块Info,上传修改(Info01)。

功能之间执行先后顺序、串行、并行、是否执行,通过操作符来决定。类似四则运算中,括号()决定执行的顺序,+、-、×、÷决定两侧的运算结果。那么可不可以定义+表示只有左侧执行成功,才执行右侧,-表示左侧执行失败再执行右侧呢?

那么按照上面的case,页面A的业务定义为:

(Account01-Account02)+Account03+Info01。

响应数据变化代替某个接口结果

通常我们是通过一个方法返回拿到结果,如果要拿到几个功能执行后的返回结果,这种方式便行不通。再加上原子功能要保持闭环,独立,不能相互依赖值传递,就更不能走传统方式。

将Model改造一下,使用监听者模式,页面需要监听哪些数据,就在初始化时注册,原子功能执行时,根据参数修改对应数据,页面实时响应数据变化即可。

Service设计

Service分为两部分:语法解析、原子功能模块注册+执行。考虑到后期模块积累过多,造成加载耗时,要支持分桶加载模块能力,例如:现在有A、B、C,3个模块,但是页面只需要调用A、C模块,那么在初始化时,可以指定自定义模块桶为:AC。

可行性分析

目前,2020年优酷相关业务建设中,有相关雏形,可以完成上述部分设计,但必须申明一点,框架还有不完善之处,后续会朝着这个方向继续探索。后续完善后,会及时更新本文档,以及对应技术文档。

好处是明显的,框架升级后,琐碎繁复的代码,再也不需要重新copy+修改,原子功能完成只需一次,但可多次使用,并且随着加入开发的同学增多,后续业务使用时,会越来越方便。

写在最后

MVVM优化后框架并不是最终解,就像文章开头讲的,本文只讨论开发模式的可能演化、优化方向;希望大家在评论区留言指正、交流。

END

长按扫描二维码关注凌云时刻

每日收获前沿技术与科技洞见

投稿及合作请联系邮箱:lingyunshike@163.com

MVVM后,下一代开发模式在哪?相关推荐

  1. 玩转Android之MVVM开发模式实战,炫酷的DataBinding!

    原文:http://blog.csdn.net/u012702547/article/details/52077515 ---------------------------------------- ...

  2. 【三种常见架构开发模式:MVC、MVP、MVVM】

    写目录 1.常见的三种开发模式 (1)MVC模式(感觉重点在view) (2) MVP模式 (感觉重点在 Presenter) (3)MVVM模式(感觉重点在VM,viewModel) 1.常见的三种 ...

  3. iOS OC mvvm开发模式

    相信大家对MVC开发都已经不陌生了,最经典开发模式 MVC构成: M:model也就是数据模型 V:View视图 C:Controller控制器 Model和View是相互独立的.View只负责页面展 ...

  4. SpringBoot中配置为开发模式,代码修改后不用重新运行

    场景 SpringBoot中配置为开发模式,修改代码后不用重新运行. 实现 打开pom.xml,添加依赖 <!-- 添加如下依赖,配置为开发模式,代码做了修改,不用重新运行--><! ...

  5. Android开发模式万佛朝中MVX(MVC、MVP、MVVM)

    今天公司的测试服务器开小差了,后台被吐槽的体无完肤,虽然我们都知道跟他没有什么关系,但是生活需要乐趣,总要有人背锅,哈哈!~~~暂时没有环境开发了,那就分享一下之前做的一篇关于Android开发模式的 ...

  6. ThinkPHP怪现象:数据表新增字段后开发模式可更新运行模式无法更新

    一.情况说明 一个已经发布的程序中,数据库原有表article,字段原有id.content.title三个字段,原程序可以正常运行,通过大D方法可以正常的更新数据库. 现在要对这个程序进行更新,数据 ...

  7. dao模式和前端控制器结合使用_前端技术及开发模式的演进,带你了解前端技术的前世今生...

    先声明,本篇不会讲带有年代性的前端发展史,不讲故事,想了解的读者可以去查阅一些其他的资料和文章,本篇仅仅从技术发展角度结合案例分析,说明前端技术的发展和开发模式的演进变化.本篇内容重点说明PC端技术, ...

  8. Asp.Net Ajax的两种基本开发模式

    Asp.Net Ajax的两种基本开发模式 引言 最近花了一些时间,将微软Asp.Net官方的Ajax视频全部看了一遍,地址是http://www.asp.net/learn/ajax-videos/ ...

  9. 前端技术及开发模式的演进,带你了解前端技术的前世今生

    先声明,本篇不会讲带有年代性的前端发展史,不讲故事,想了解的读者可以去查阅一些其他的资料和文章,本篇仅仅从技术发展角度结合案例分析,说明前端技术的发展和开发模式的演进变化.本篇内容重点说明PC端技术, ...

  10. 转 下一代云计算模式:Docker正掀起个性化商业革命

    下一代云计算模式:Docker正掀起个性化商业革命 作者: 吴宁川  来源: ITValue  发布时间: 2015-09-20 10:41  阅读: 14052 次  推荐: 26   原文链接   ...

最新文章

  1. linux sntp 代码,C语言window(linux)平台的SNTP实现
  2. python爬网页源码_python爬虫爬取网页的内容和网页源码不同?
  3. Tensorflow安装与测试
  4. 安卓APP动态调试技术
  5. 【codecombat】 试玩全攻略 第十四关 已知敌人
  6. osg 三维gis开发_三维GIS平台的可视化应用 (下)
  7. zookeeper专题:zookeeper集群模式下,leader选举流程分析
  8. [转] Agile Software Development 敏捷软件开发
  9. 阶段1 语言基础+高级_1-3-Java语言高级_09-基础加强_第2节 反射_8_反射_Class对象功能_获取Field...
  10. 物流管理系统(数据库+后台+springMVC+Mybatis+layui)(一)
  11. Nodejs BFF 开发 8 个月的心路历程
  12. 计算机网络常用端口号大全
  13. 地壳中元素含量排名记忆口诀_【化学好好玩】用口诀帮你速记忆化学知识
  14. 计算机现在追寻谁的原理,一路追寻-CS考研经验总结_计算机与软件_考研论坛(kaoyan.com)...
  15. 长江大学计算机科学学院德贵奖学金,关于做好2019年各类奖学金评选的通知
  16. 用php获取设备信息
  17. 仿抖音效果的数字时钟罗盘
  18. 国际标准书号 (International Standard Book Number, ISBN)是专门为识别图书等文献而设计的国际编号
  19. 服务器硬盘选金盘好吗,WD 西部数据 企业级 10T金盘与8T金盘 对比测试
  20. virtualBox新建虚拟电脑

热门文章

  1. 批量删除2012年9月份以前的表
  2. 【技术贴】解决开机本地连接出来慢,本地连接开机后出来时间慢
  3. ubuntu下切换到root用户
  4. LCS2005标准版部署
  5. web调试代理工具Whistle
  6. solrCloud相关的管理命令
  7. BZOJ4602: [Sdoi2016]齿轮(并查集 启发式合并)
  8. jquery 给a标签加上或去掉下划线
  9. 固定背景图的高度,让宽度自适应
  10. 转:zTree树控件入门之checkbox:如何动态设置节点的checkbox选择框启用与禁用状态(chkDisabled)...