也谈MVVM

作者: 庸者的救赎 | 来源:发表于2016-11-27 21:56 被阅读533次

    先说MVC吧

    MVC,全称是 Model View Controller,是模型 (model)-视图 (view)-控制器 (controller) 的缩写。它表示的是一种常见的客户端软件开发框架;
    MVC这个概念最早出现在上个世纪八十年代(目测本文的读者都还没有出生,当然笔者也没有出生)被提出,之后被广泛的应用于各类软件开发中.
    iOS开发也不例外,iOS的系统架构就是典型的MVC,并且为我们实现了V层和C层的基础,然后开发者根据相应的数据补充M.这一切看起都很合理,而且开发者也一直都这么做着,并没有什么不妥
    嗯,是的,没毛病...

    但是事实真的如此么?
    事实是,很多维护者会抱怨前人的代码多烂多烂,真的没法看,设计模式一塌糊涂等等;
    这时候的MVC可能会变成(Massive View Controller),controller里面塞满了各类业务代码,多大上千行,甚至更多,如果注释写的好一些,勉强能看,如果没有注释...
    为什么会这样?这里的原因太多了,比如有些开发者在做iOS之前并没有听说过MVC,有些即使知道MVC,也根本无法明确MVC到底干嘛的?面试官经常会问到这个问题,而得到的答案也仅仅是解释MVC概念之类,很少有人会在解释完概念之后再去仔细的阐述一下结构设计,代码规范之类...

    下面我们仔细剖析一下,到底该如何MVC?

    真正的MVC

    我们来看看 MVC 这种架构的特点。其实设计模式很多时候是为了 Don't repeat yourself 原则来做的,该原则要求能够复用的代码要尽量复用,来保证重用。在 MVC 这种设计模式中,我们发现 ViewModel 都是符合这种原则的。

    对于View来说,你如果抽象得好,那么一个App的动画效果可以很方便地移植到别的App上,而Github上也有很多UI控件,这些控件都是在View层做了很好的封装设计,使得它能够方便地开源给大家复用。

    对于Model来说,它其实是用来存储业务的数据的,如果做得好,它也可以方便地复用。比如我当时在做有道云笔记 iPad 版的时候,我们就直接和iOS版复用了所有的Model层的代码。在创业做猿题库客户端时,iOSiPad 版的 Model 层代码再次被复用上了。当然,因为和业务本身的数据意义相关,Model 层的复用大多数是在一个产品内部,不太可能像 View 层那样开源给社区。

    说完 ViewModel 了,那我们想想 ControllerController 有多少可以复用的?我们写完了一个 Controller 之后,可以很方便地复用它吗?结论是:非常难复用。在某些场景下,我们可能可以用addSubViewController 之类的方式复用 Controller,但它的复用场景还是非常非常少的。

    如果我们能够意识到 Controller 里面的代码不便于复用,我们就能知道什么代码应该写在 Controller 里面了,那就是那些不能复用的代码。在我看来,Controller 里面就只应该存放这些不能复用的代码,这些代码包括:

    • 在初始化时,构造相应的 View 和 Model。
    • 监听 Model 层的事件,将 Model 层的数据传递到 View 层。
    • 监听 View 层的事件,并且将 View 层的事件转发到 Model 层。

    MVC反面教材

    直接上代码吧:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell", for: indexPath) as! TableViewCell
        cell.textLabel?.text = "二狗子"
        cell.imageView?.image = UIImage(named: "")
        return cell
    }
    

    上面这段代码,咋一看也没啥,因为只有6行而已,但是这是因为上面的cell数据加载很简单,只有一个textimage,但实际开发中,我们的数据可不是这样的,如果是新浪微博那种cell我想,单单是cell的数据加载都能写个上百行;所以这种写法是完全违反MVC原则的,因为你在C里面干了V的事情, C只应该做数据传递;所以,严格遵循MVC原则的写法是,不管cell的数据加载多么负责,代码都应该是下面这样的:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell", for: indexPath) as! TableViewCell
        cell.userModel = dataModel[indexPath.row]
        return cell
    }
    

    如果你的tableview是个标准的反面教材,请在评论区留下你的大名📌

    这里只是简单的做了一些代码结构的调整,但是确实符合了MVC原则,但是在controller中往往不止这些东西,controller最头疼的问题,就是网络请求问题,因为复杂的界面会涉及到很多数据请求,而这些请求也会伴随着界面和数据的变化,这些逻辑写上去,那么controller的代码量瞬间就上去了,几个版本迭代过去,你懂的!所以,达到上千行只是时间问题?

    何解?
    在网上关于这个问题的答案有很多,比如分离网络业务层,直接放到一个专门的业务模块里面,MVVM就是在这种情况下衍生出来的.

    MVVM

    MVVM的历史,这里就不赘述了,感兴趣的同学直接百度,一大把,先看看一张基本上只要谈到MVVM都会放的一张图:

    MVVM结构图

    上面这张图,我想很多人肯定不止一次看到过

    这个图准确的描述了什么是MVVM:一个MVC的增强版,让viewviewcontroller直接结合在一起,使用ViewModel进行链接,并将逻辑从controller里面移出放到ViewModel;MVVM听起来很复杂,但是他本质还是MVC,只不过在结构上做了调整;这样viewmodel彻底解耦了,那么这个时候他们之间的通信会变得有些奇怪了,因为他们中间跨越了一个层,所以在MVVM的使用当中,通常会利用双向绑定技术,使得Model的变化能同步更新到View
    那么这里就得提到一个框架:ReactiveCocoa(swiftObjective - C都支持,但是在Swift上更推荐使用RxSwift);

    ReactiveCocoa是一个基于Cocoa封装的函数响应式框架,使用它可以轻松的实现数据的绑定;所以,每每谈到MVVM的时候,总会提到它;但ReactiveCocoa可以不想其他三方框架那般,看看Document就可以开心的撸起来了,ReactiveCocoaDocument都能写成一本厚厚的书了,而且最关键的是,它的编程思想,函数式,响应式,数据流...
    还有它那魔性的语法.

    当然了ReactiveCocoa也提供了很多便捷:

    • 函数式,提供了很多函数式操作(对于Objective - C来说,Swift本身自带)
    • 数据绑定,很多时候可以代替KVO,delegate
    • 动态声明

    更多信息可以去官网阅读相关文档,本文这里不做太多探讨;

    要换MVVM?

    既然MVVM有那么多好处,为何不换?
    在移动开发领域,MVVM提出也不短了,可大部分项目还是使用MVC,只有少部分项目会用;还有一部分项目会有专门的架构师,为项目设计架构,他们会搞出一些大家都不懂的东西,然后在某个分享会上分享给大家;
    但是!
    我们要想清楚,你的项目真的需要MVVM么?
    不一定吧?
    如果你的项目本来就不复杂,为何要换?MVC就挺好的,别听那些"分享"
    笔者不是说那些分享不好,好,确实好,但,那是在他们的项目上用呀,他们都是就职于BAT这样的大厂的

    一笑而过?

    通过上面的阅读,相信你已经对MVCMVVM有所了解,那么问题来了.

    该用什么?

    相信,很多iOS开发者在找工作面试的时候都被问过MVVM,基本上都快成了必问点了

    我们不好说,哪个更好,哪个更适合.根据自己的情况选择
    MVVM的学习路线相对要难很多,但是空闲的时候尝试一下也是个不错的实践,其中收获必定不小的
    至少下次吹牛或面试的时候,你也多一些谈资不是?

    生命不息,折腾不止...
    I'm not a real coder, but i love it so much!

    相关文章

      网友评论

        本文标题:也谈MVVM

        本文链接:https://www.haomeiwen.com/subject/cbvnpttx.html