使用当前的实践(至少使用WPF和Silverlight),我们在视图模型中看到通过命令绑定绑定的视图,或者我们至少看到视图模型中处理的视图事件。这似乎违反了SRP,因为视图模型不仅模拟视图状态,而且响应视图(用户)。其他人问how to build view models without violating SRP或问whether their implementations do so(这最后是MVC中的控制器,但大致相似)。
目前的做法是否违反了SRP?或者“视图模型”真的是一组不违反SRP的东西?为了解决这个问题,似乎我们需要知道什么是单一责任,或者概念中是否存在多个职责,是否将个别职责分解出来,符合SRP。我不确定。
[T]他的ViewModel是一个“视图模型”,意思是它是视图的抽象,也用于视图和模型之间的数据绑定
对于SRP来说这似乎已经足够了,但后来这篇文章说明了(我强调了)
[ViewModel]充当数据绑定器/转换器,将模型信息更改为查看信息并将命令从视图传递到模型
在关于视图模型角色的Prism blog post中,作者说(再次,我的重点)
它归结为视图模型是以下的组合:
- 视图的抽象
- 命令
- 值转换器
- 查看状态
我确信我错过了许多定义,但它们似乎属于这些类别:
如果你很好奇,我“关心”这个因为(2)感觉正确,但似乎与现行的实施相反。
答案 0 :(得分:10)
单一责任为Martin defines it:
“从来没有超过一个改变的理由。”
就MVVM而言,ViewModel实际上只是Presentation Model的专门实现。
所以虽然可以说演示模型应该只代表用户界面的状态,并且演示者/控制器应该始终在UI和Presentation Model之间代理命令。如果遵循这个想法,使用 SRP除以状态和命令,则添加命令不应该影响表示状态的类。因此MVVM会打破SRP。
我认为这是抓住稻草。 MVVM是一个相当专业的实现,主要用于WPF / Silverlight(and now browser clients)。
模式旨在使设计更简单,而替代方案更麻烦或更难维护。由于MVVM旨在利用表示技术的极其丰富的数据绑定功能,因此值得权衡。
答案 1 :(得分:6)
没有! MVVM没有违反SRP,(程序员会这样做,哈哈!)
使用MVVM模式没有理由需要忽略SRP。 MVVM并不意味着只有一个Model类,一个View-Model类和一个View Class。当然,如果你只有一个View Class,你只能显示一个简单的屏幕。
View层中的那些类应该负责一件事;做,决定或包含。视图可以包含多个子视图,这些子视图的作业是执行用户交互的某些部分。考虑一个基本形式,它有一个显示网格,网格中的项目可以编辑,并有一个“保存”按钮。
主视图将是另外两个视图的容器; datagrid(用户控件或其他东西)和命令控件。然后,datagrid负责选择正确的子视图以呈现数据;在essense它是一个数据集的容器。编辑项目的视图是数据网格的子视图,而后者又是主视图的子视图。最后,命令控件是一组按钮(在这种情况下是一个按钮),其唯一的责任是引发用户发出命令的信号。
通过这种方式,编辑视图(由DataGrid使用)与使用它的内容无关,并且有一个责任;与命令控件相同。同样,DataGrid并不关心谁使用它,只是它可以包含Edit View(child)。尼斯SRP那里。
匹配视图(和子视图)的ViewModels也负责一件事。编辑视图模型是编辑视图绑定的容器;它只包含可以显示/编辑的数据字段。当它的一个属性发生变化时,它并不关心任何事情。命令按钮视图模型是一个可以完成任务的类。它的命令绑定到按钮,它将根据用户点击的内容工作。它必须能够访问ViewModel的其他部分才能完成它的工作。
主页面View Model包含其他子视图。它的唯一责任是作为初始化程序,创建所有必需的ViewModel实例,并将构造函数参数传递给其他ViewModel实例(例如,命令按钮视图模型,以便它知道从哪里获取数据)
很自然地将一大堆功能塞入一个大型View将绑定的ViewModel中。但它不一定是这样,并且可以在MVVM中维护SRP。
MVVM的主要目标是允许可测试的设计,模型层可以独立测试,模型中的所有类都可以轻松地遵循SRP。可以在不需要视图的情况下测试ViewModel;在ViewModel中思考SRP变得更加棘手,但它肯定是可行的;只记得打破你的课程,这样他们只有一个问题。 View绑定了ViewModel,幸运的是,你对ViewModel的测试使得查看超级容易。请记住,您可以让每个View-let遵守SRP成为更大的集团View(容器)的一部分。
TL; DR? 要直接回答您的问题,View是一组不会破坏SRP的类。因此,当ViewModel从View(s)(View-First)中抽象出来时,它们也是符合良好SRP的类的集合。
答案 2 :(得分:5)
我认为围绕MVVM的许多当前做法都违反了SPR(至少)。这是另一种情况,简单地将控制器添加回MVVM将彻底解决所有问题。我称之为MVCVM:)
我们在所有最近项目中成功使用的模式是在模块中注册控制器仅,并在启动时初始化它们。控制器非常轻薄,是唯一需要在应用程序监听或发送消息的生命周期中闲逛的东西。在他们的初始化方法中,他们然后注册他们需要拥有的任何东西(视图和视图模型等)。这种轻量级逻辑内存模式也可以实现更轻薄的应用程序(例如WP7更好)。
正如您所发现的那样,使用虚拟机的问题是,最终您遇到了需要了解视图,命令或其他内容的情况,而不应该参与自尊的ViewModel!
我们遵循的基本规则是:
最后两点是你永远不应该打破的点,或者关注点的分离会消失。
简单地将控制器添加回MVVM组合似乎可以解决我们发现的所有问题。 MVVM是一件好事,但为什么它们不包含控制器? (但这当然只是我的意见):)
答案 3 :(得分:2)
它归结为视图模型是以下内容的组合:
- 视图的抽象
- 命令
- 值转换器
- 查看状态
我不明白为什么你把前两个项目分开了。命令是视图的一部分。
至于其他人 - 你是对的。在某些情况下。我已经构建了应用程序,其中值转换和维护视图状态的任务足够复杂,单个视图模型类无法完成所有这些任务,我将它们分解为与VM互操作的单独类。
因此?