关于c#:MVVM优于MVC的好处

Benefits of MVVM over MVC

最后开始开发Silverlight,我遇到了MVVM。我对MVC很熟悉,我读到的那篇文章说,因为XAML,MVC无法运行。在XAML方面没有太多经验显然是我没有得到这一点的原因。

有人能解释为什么MVC不适合,为什么MVVM更适合Silverlight开发吗?

谢谢JD


这是一个非常细微的区别,我可以通过比较ASP.NET中的MVC和WPF中的MVVM来最好地解释这一点。

在ASP.NET MVC中,请求来自Web服务器,由控制器直接处理。控制器确定适当的视图并用模型填充它。然后,控制器将这些实例发布到底层系统,该底层系统将结果呈现给客户机。您可以看到控制器是第一个也是最后一个动作。

在MVVM中,UI(视图)面向用户并直接接受用户输入。在视图中,此活动将触发视图模型(视图的DataContext)中的命令。控件流到ViewModel,后者解释视图已发送的内容并准备其模型。控件流回视图后,它会根据模型中的更改自行更新。如果需要新的视图,则ViewModel会将其与NavigationService(或应用程序使用的任何导航方法)通信,后者是窗口或框架的权限——UI组件。您可以看到,viewModel并不是第一个和最后一个要执行的操作;该视图在MVC中扮演的角色要比在MVC中扮演的角色大得多。

WPF/Silverlight的体系结构就是这样做的原因。控制器无法控制/替换命令、绑定和导航基础设施;它们与UI紧密集成。因此,控制器必须坐在视图下方,扮演一个更被动的角色。


MVVM的设计主要是基于XAML,为了使数据绑定更加简单,它与MVP非常相似。主要的好处是操作用户界面的方法更简单(视图模型或演示者负责处理该任务,而不是模型在控制器操作后必须向视图触发事件)。

我遇到的两篇最好的文章帮助我理解了这些原则:MVC vs MVP vs MVVM和MVVM,适用于像我或MVVM这样的受影响人,以及它对我意味着什么。


分离组件好的。

在MVC中,组件之间有一个三角形的关系。即:控制器拥有视图和模型。视图依赖于模型的定义。模型需要满足视图的要求。想想中心(控制器)和辐条架构(视图和模型)好的。

在MVVM中,想象一个三角形变平,每个组件只知道链中的另一个组件。即:视图->视图模型->模型好的。

模型不知道堆栈中的任何内容。ViewModel只知道该模型视图只知道视图模型——它不知道模型。好的。

为什么这很重要?好的。

这是原始问题的核心。好的。

主要目的是进一步抽象您的体系结构。这通常会导致更多的代码,但对象之间的接触点更少。减少接触点很重要,因为这会导致代码更加敏捷。A类与B类的耦合/接触越多,A类变化的影响就越大。减少变更的影响是良好体系结构的关键好处之一。好的。

为了充分理解这一点,思考组件真正代表什么是很有帮助的。什么是视图、控制器、视图模型或模型?它们是字面定义还是抽象概念?好的。

在我的经验中,将模型视为处理数据构造和持久性的类/对象集群更为有益。它不仅仅是一个有属性的普通老对象。它是一个执行数据提取、数据保存的类,是一个构造普通旧对象的工厂。它是一个外观层,为数据提供了一个清晰的API。这个立面层应该直接从视图中引用吗?好的。

在我看来,这不应该。在MVC中,这个答案也是"否"。控制器从模型中获取数据。在这方面,MVC和MVVM实现了相同的目标。这两种架构的不同之处在于数据和视图的链接方式。好的。

与模型一样,视图也可以是类的集合,这些类相互协调,呈现一个表示视图。在移动平台的情况下,这可能包括视图控制器+视图(iOS上的视图控制器,Android上的活动)。在很多情况下,您需要一个类来将视图文档加载到内存中并更新视图属性。这里有很多工作要做。在MVC中,控制器很快就变成了"厨房水槽"类——一种与当前用户上下文相关的垃圾场。好的。

当您将它与应用程序中的几十个潜在视图相乘时,您最终会在后端模型代码和前端视图代码之间产生大量的依赖关系。对于大型控制器类,这些依赖性并不是很明显。好的。

平缓你的依赖好的。

MVVM使依赖关系变平。这就产生了焦点。什么是焦点?在不干扰所有其他依赖项的情况下处理单个功能的能力。现在您可以开始在以前被认为不稳定的代码上编写单元测试。好的。

视图模型充当视图和模型之间的立面。视图模型满足视图的需求——从技术上讲,视图应该拥有视图模型。如果视图需要来自多个源的数据,那么视图模型将独立数据源的组合封装为一个统一的、非规范化的对象。如果视图需要调回模型或其他目的地,那么视图模型提供钩子并路由适当的调用。好的。

考虑一下网络配线架是如何工作的。乍一看,这似乎是多余的——为什么不简单地将您的以太网从点A连接到点B呢?但是根据经验,您会理解,一个接线板为您提供了一个关键的抽象部分,它允许您在不影响点A的情况下更改点B的路由。这就是您的视图模型正在做的。好的。

既然在视图和模型之间有了一个清晰的抽象,那么结果应该是视图/控制器只与表示有关。这意味着它不应该处理本地化或格式化——它获取数据并显示数据。您的视图模型是放置此类视图前数据按摩的理想位置。假设您需要根据条件筛选数据。同样,视图模型对模型数据是了解的(您的视图不是),是放置此类代码的好地方。好的。

一旦您开始以这种方式组织应用程序需求,您的视图/控制器代码就变得更干净了,当需要更改某些内容时,影响就更明显了,这会导致更少的错误。好的。

可测试性好的。

关于可测试性的最后一个注意事项:通过扁平依赖关系,可以更容易地将模拟依赖关系注入到测试中。它使测试更加简单和简洁。您的视图模型成为您可以定义清晰测试用例的对象。好的。好啊。


我认为另一个好处是学习曲线。由于前端技术中的大多数开发人员都使用了MVVM类型的编码方式,因此他们采用MVVM类型比使用控制器模型更容易,因为在控制器模型中,他们需要将每个请求从视图传递到控制器,并让它与模型通信。


我认为MVVM比MVC更适合XAML。说MVC"不适合"有点夸张。

为什么MVVM更好?主要是因为XAML中有出色的数据绑定和命令绑定。请参阅本文。