作者:Soroush Khanlou,原文链接,原文日期:2015-12-17
译者:zltunes;校对:Channe;定稿:shanks

我写过许多关于让 ViewController 变得更轻量的文章,Model-View-viewmodel 是一种常用的可以实现该目的的设计模式。我觉得 MVVM 是一种反人类的设计模式,它使架构更加混乱而非清晰。View Model的命名很糟糕,它只是架构优化的权宜之计。对我们来说放弃这一模式反而更好。

MVVM 命名很糟糕

名称是很重要的。一个理想的名称能够有效地传达出对象是干什么的,扮演什么角色以及怎么使用它。View Model这一名称则没有发挥任何作用。

在我看来,View Model这个十分抽象的名称实际上指的是两个截然不同的设计模式。

View Model的第一种含义是 model for the view(视图的模型)。这是一个愚蠢的对象(严格来讲 Swift 中叫struct),用来传递给某个视图去填充它的子视图。它不应该包含任何逻辑或方法。类似于UILabel需要一个字符串,UIImageView 需要一张图像,ProfileView需要一个Profileviewmodel。该对象直接传递给ProfileView,它允许你的子视图是私有的而非暴露给外界,这是很有用的一点。我更喜欢把这种设计模式叫做view data,因为它把自己从view model的另一种定义的包袱中除去了。

View model另一种含义是介于模型和视图控制器之间的一种模糊、抽象的对象。负责将数据传递给表示层,有时候也作为网络和数据库通道,或者表单验证以及其他类似的任务。这种“万金油”式的对象可以为你的控制器减压,但往往最后会成为一个新的“下水道”,什么任务都往里面堆。

MVVM 引进太多职责

命名不够具体,导致这个类的任务无休止地增长。到底哪些任务应该交给view model?没有人知道,好像什么都能交给它。

让我们看一些例子。

  • 这里将网络请求放入view model,并建议你添加验证和表示的逻辑。

  • 这里只展示了如何将表示逻辑放到view model中,并提出为什么不把它命名为Presenter的问题。

  • 这里讲到用view model上传数据并绑定到ReactiveCocoa

  • 这里用view model进行验证和获取数据。

  • 这里明确建议你在view model中放入“其他代码”:

view model 非常适合干这些事:验证逻辑、用户输入、视图展示逻辑、网络请求以及其他代码。

没有人知道view model到底是什么意思,所以无法就“哪些功能交给 view model”达成一致。它本身概念过于抽象。这些作者对一个 Validator 类、Presenter 类或者 Fetcher 类该做什么是没有异议的,这些名字都起得很好,能准确传达出对应类扮演的角色。

给用途截然不同的对象起同一个名字只能给读者造成困惑。如果我们不能就view model的功能达成一致,为什么要给他们起这个名字?

这种看法面临着一个类似的挑战,我们发现controller这个名称同样太宽泛,无法包含一系列确切的任务。

你自己的类叫什么名字完全由你决定,选个好听的就是了!

MVVM 不改变你的架构

view model 并不能从根本上改变你的应用程序的架构。这两张图有什么不同(原图)?

不需要利用先进的图片理论你也能看出这两张图几乎是一样的。

我能想到的 MVVM 模式最大的好处就是它把“下水道”从苹果自带的 view controoller类转移到了view model这一自定义的对象。view controller只需要专注于视图生命周期事件即可,变得很简洁。尽管如此,还是有“下水道”存在,仅仅是转移了而已。

由于view model只是给 app 添加的一层定义简陋的模块,仍无法解决复杂性的问题。如果你为了避免view controller过于臃肿而创建了view model,那么当你的代码规模加倍的时候会发生什么?也许我们可以加一个controller-model层。

view model方案不能大规模扩张。对于它想解决的问题来说只能做到缓解而无法完全避免。我们需要一个更佳的方案,比如可以尝试随着一个对象的增大不断去分解它,像细胞进行有丝分裂一样。View model只是权宜之计。

其他社区也曾面临该问题

几年前 Rails 社区也曾遇到这种问题,他们也想出了解决方案,我们可以从中获得一些启示。首先他们有臃肿的controller以及几乎没什么内容的model。这种情况下很难进行测试,所以把所有的逻辑代码分解到model中,最终controller变得很简洁,model变得臃肿。复杂的model依赖于ActiveRecord和数据库,依旧难以测试,仍需要继续分割成更小的部分。

7 Patterns to Refactor Fat ActiveRecord Models 这篇博客受到8 Patterns to Help You Destroy Massive View Controller的影响,是这一系列想法下的产物。总而言之你仍需要将那些恼人的东西分割成小的单元,“转移下水道”的做法仅是缓解之计。

view model是一种完全无法应对现代编程挑战的做法,命名糟糕,对自己包含的功能不明确,最终面临和controller一样的问题。它只是对复杂情形的权宜之计,如果我们不去避免这种做法,很快又会面临同样的问题。

本文由 SwiftGG 翻译组翻译,已经获得作者翻译授权,最新文章请访问 http://swift.gg。

MVVM 不是那么好的更多相关文章

  1. Swift教程17-淡化MVC,使用MVVM框架开发轻巧便于维护的iOS/android app

    MVVM是微软提出一种移动开发框架,旨在针对传统的MVC框架,解决传统的MVC框架的控制器的臃肿问题.M:Model模型,也就是数据模型;比如一条微博,对应的所有字段合成一条微博整体,这个整体就是ModelV:View视图,只用来显示的视图,如iOS的UIView,Cell;当然在iOS中Storyboard中,view总是和控制器关联,这并不是严格的view如果我们纯手写代码定义一个view那么

  2. Swift 2.0 下面向协议的MVVM架构实践

    本文由CocoaChina译者lynulzy翻译原文:Swift2.0:Protocol-OrientedMVVM自从令人兴奋的[《面向协议的编程方法》]在Swift的WWDC大会上发布以来。我已经在之前的博客中使用过MVVM架构,如果你想了解更多MVVM相关知识请参考[这里]。接下来我将讲解,如何添加面向协议。switchToggle.onTintColor=switchColorself.onSwitchToggleHandler=onSwitchToggleHandler虽然在这种情况下看起来并不是

  3. Swift教程17-淡化MVC,使用MVVM框架开发轻巧便于维护的iOS app

    overridefuncawakeFromNib(){super.awakeFromNib()}overridefuncsetSelected{super.setSelected}/***配置Cell的内容方法*/funcconfigCellWithStatusModel(model:StatusModel!){self.imageView2.setimageWithURL;background-color:inherit">placeholderImage:UIImage)self.textLabel2

  4. Swift开发黑科技:还在争论MVC和MVVM?现在你应该试试MVP!

    我下定决心重构自己的代码,下面步入正题,结合Swift开发大会的一些分享,让我们谈谈架构。现在数据工程里面的目录是这样的:模型代码:为了简单我都使用了String类型的数据,至于为什么要使用struct而不使用class,大家可以参考WWDC2015的414号视频,讲的非常清楚,我自己的项目中的数据模型已经全部转成struct了,我会在后面专门写博文讲解struct,这里就不赘述了。

  5. MVVM 不是那么好

    我觉得MVVM是一种反人类的设计模式,它使架构更加混乱而非清晰。MVVM命名很糟糕名称是很重要的。ViewModel这一名称则没有发挥任何作用。ViewModel的第一种含义是modelfortheview。MVVM引进太多职责命名不够具体,导致这个类的任务无休止地增长。MVVM不改变你的架构viewmodel并不能从根本上改变你的应用程序的架构。我能想到的MVVM模式最大的好处就是它把“下水道”从苹果自带的viewcontrooller类转移到了viewmodel这一自定义的对象。

  6. Swift学习第十一枪-基于协议的MVVM模式的实现

    下面是我的新建的Swift学习交流群,欢迎大家一起来共同学习Swift。不管是IOS还是Android,就三种常用模式,MVC,MVP,MVVM网上的资料非常之多,对于MVVM大家估计都有所了解,我在这里就简单的以图示的形式给大家展示。

  7. 关于MVVM的理解

    MVVM中VM到底是个什么角色?MVVM简介关于MVVM,相信大家或多或少都有了解。引用MVVM介绍文中一图受MVC或MVP架构的影响,对MVVM最初印象以为这是一个以viewmodel为核心,处理View和Model的开发架构。于是乎在原有MVC的基础上,创建了一个所谓的viewmodel对象,然后把ViewController中的代码移到viewmodel中,在viewmodel里面处理View以及Model的所有逻辑。完整结构如图所示Model并不表示ModelMVVM架构中的M,并不表示Model

  8. 开发Swift iOS应用程序“正确的方式”

    最近,我学习了Swift和开发iOS应用程序的基础知识。现在,我想自己开发一个真正的应用程序,但我非常关心编写好的代码,所以我已经寻找“最佳实践”,“设计模式”和“正确的方式”来实现它。在我的搜索中,我发现这个greattutorial关于SwiftiOS应用程序中通常使用的所有设计模式,以及他们使用的示例。不应该将httpClient和persistencyManager声明为协议,然后HttpClient和PersistencyManager类实现该协议?我应该在哪里告诉应用程序?最后但并非最不重要的

  9. android – MVVM Dagger2与组件中存在匹配键的绑定

    我正在使用以下谷歌示例项目:https://github.com/googlesamples/android-architecture-components作为我的新项目的参考,并且难以尝试向项目添加第二个活动.这是编译时遇到的错误这是我的代码ActivityModuleAppComponentAppInjector的AppModuleFragmentBuildersModule注射viewmod

  10. javascript的23种设计模式示例总结大全

    这篇文章主要为大家介绍了javascript的23种设计模式的总结大全,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

随机推荐

  1. Swift UITextField,UITextView,UISegmentedControl,UISwitch

    下面我们通过一个demo来简单的实现下这些控件的功能.首先,我们拖将这几个控件拖到storyboard,并关联上相应的属性和动作.如图:关联上属性和动作后,看看实现的代码:

  2. swift UISlider,UIStepper

    我们用两个label来显示slider和stepper的值.再用张图片来显示改变stepper值的效果.首先,这三个控件需要全局变量声明如下然后,我们对所有的控件做个简单的布局:最后,当slider的值改变时,我们用一个label来显示值的变化,同样,用另一个label来显示stepper值的变化,并改变图片的大小:实现效果如下:

  3. preferredFontForTextStyle字体设置之更改

    即:

  4. Swift没有异常处理,遇到功能性错误怎么办?

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. 字典实战和UIKit初探

    ios中数组和字典的应用Applicationschedule类别子项类别名称优先级数据包contactsentertainment接触UIKit学习用Swift调用CocoaTouchimportUIKitletcolors=[]varbackView=UIView(frame:CGRectMake(0.0,0.0,320.0,CGFloat(colors.count*50)))backView

  6. swift语言IOS8开发战记21 Core Data2

    上一话中我们简单地介绍了一些coredata的基本知识,这一话我们通过编程来实现coredata的使用。还记得我们在coredata中定义的那个Model么,上面这段代码会加载这个Model。定义完方法之后,我们对coredata的准备都已经完成了。最后强调一点,coredata并不是数据库,它只是一个框架,协助我们进行数据库操作,它并不关心我们把数据存到哪里。

  7. swift语言IOS8开发战记22 Core Data3

    上一话我们定义了与coredata有关的变量和方法,做足了准备工作,这一话我们来试试能不能成功。首先打开上一话中生成的Info类,在其中引用头文件的地方添加一个@objc,不然后面会报错,我也不知道为什么。

  8. swift实战小程序1天气预报

    在有一定swift基础的情况下,让我们来做一些小程序练练手,今天来试试做一个简单地天气预报。然后在btnpressed方法中依旧增加loadWeather方法.在loadWeather方法中加上信息的显示语句:运行一下看看效果,如图:虽然显示出来了,但是我们的text是可编辑状态的,在storyboard中勾选Editable,再次运行:大功告成,而且现在每次单击按钮,就会重新请求天气情况,大家也来试试吧。

  9. 【iOS学习01】swift ? and !  的学习

    如果不初始化就会报错。

  10. swift语言IOS8开发战记23 Core Data4

    接着我们需要把我们的Rest类变成一个被coredata管理的类,点开Rest类,作如下修改:关键字@NSManaged的作用是与实体中对应的属性通信,BinaryData对应的类型是NSData,CoreData没有布尔属性,只能用0和1来区分。进行如下操作,输入类名:建立好之后因为我们之前写的代码有些地方并不适用于coredata,所以编译器会报错,现在来一一解决。

返回
顶部