《UI层的设计模式——从Script、Code Behind到MVC、MVP、MVVM》(转)

MVC和MVP的区别

原址:http://www.cnblogs.com/end/archive/2011/06/02/2068512.html

MVC和MVP的区别

MVC和MVP到底有什么区别呢?

《UI层的设计模式——从Script、Code Behind到MVC、MVP、MVVM》(转)_第1张图片

从这幅图可以看到,我们可以看到在MVC里,View是可以直接访问Model的!从而,View里会包含Model信息,不可避免的还要包括一些业务逻辑。

在MVC模型里,更关注的Model的不变,而同时有多个对Model的不同显示,及View。

所以,在MVC模型里,Model不依赖于View,但是View是依赖于Model的。不仅如此,因为有一些业务逻辑在View里实现了,导致要更改View也是比较困难的,至少那些业务逻辑是无法重用的。

Visual Studio等快速开发工具,让我们很难把View和Controller分开,我们总是直接在View的事件响应函数里完成了Controller的代码。而在ASP.NET和XAML里,使用了一种叫做Code-Behind的技术,可以把View和Controller进行分离。这样,View就可以完全由UI设计工程师来完成,而Controller由程序员来完成,两者可以直接合成不需要像现在一样再由程序员做很多的工作。

把Controller和View混在一起,有什么问题?

1.难以测试。

  必须手动点击,使用各种自动化的测试工具。

2.代码难以重用。

  UI是很难重用,因为要求总是不同。所以,导致重复的代码四处都是,维护麻烦。

MVP是如何解决MVC的问题的?

《UI层的设计模式——从Script、Code Behind到MVC、MVP、MVVM》(转)_第2张图片

在MVP里,Presenter完全把Model和View进行了分离,主要的程序逻辑在 Presenter里实现。而且,Presenter与具体的View是没有直接关联的,而是通过定义好的接口进行交互,从而使得在变更View时候可以 保持Presenter的不变,即重用!

不仅如此,我们还可以编写测试用的View,模拟用户的各种操作,从而实现对Presenter的测试--而不需要使用自动化的测试工具。

我们甚至可以在Model和View都没有完成时候,就可以通过编写Mock Object(即实现了Model和View的接口,但没有具体的内容的)来测试Presenter的逻辑。

在MVP里,应用程序的逻辑主要在Presenter来实现,其中的View是很薄的一层。 因此就有人提出了Presenter First的设计模式,就是根据User Story来首先设计和开发Presenter。在这个过程中,View是很简单的,能够把信息显示清楚就可以了。在后面,根据需要再随便更改View, 而对Presenter没有任何的影响了。

如果要实现的UI比较复杂,而且相关的显示逻辑还跟Model有关系,就可以在View和 Presenter之间放置一个Adapter。由这个 Adapter来访问Model和View,避免两者之间的关联。而同时,因为Adapter实现了View的接口,从而可以保证与Presenter之 间接口的不变。这样就可以保证View和Presenter之间接口的简洁,又不失去UI的灵活性。

在MVP模式里,View只应该有简单的Set/Get的方法,用户用户输入和设置界面显示的内容,除此就不应该有更多的内容,绝不容许直接直接访问Model--这就是与MVC很大的不同之处。

参考:


MSDN的MVP介绍 
一个不错的视频演示 
Presenter First 
The Humble Dialog 
-----------------------------------------------

Alex在他的blog中对于mvc 与mvp 之间的比较:

【译文】:


Model View Presenter vs Model View Controller
简介

在我工作中经常需要处理一些由于开发人员没能很清楚地理解MVC和MVP模式的区别的情况下使用它们而产生的问题。在这篇文章中我将会阐述一下我对两者之间区别的一些理解。
在N层体系结构中MVC/P 模式仅仅只是用于表示层(presentation layer),理解这一点很重要。这两个模式并不是关于怎么构建数据层(data layer)和服务层(service layer)的,而是关于怎么将数据(data)从用户接口(view)中分离出来,以及用户接口如何与数据进行交互的。这些模式的使用让解除你的程序中表示层对对数据和控制逻辑的依赖,从而可以自由的变更表示层。


这两种模式中三个部分的一般理解

1、模型(Model)表示数据模型和业务逻辑(business logic)。模型并不总是DataSet,DataTable之类的东西,它代表着一类组件(components)或类(class),这些组件或类 可以向外部提供数据,同时也能从外部获取数据并将这些数据存储在某个地方。简单的理解,可以把模型想象成“外观类(facade class)”。【译注:这里的外观是指“外观模式”中所说的外观。外观的一般作用是为一个复杂的子系统提供高层次的简单易用的访问接口,可以参看下面的图来理解它的原理:
《UI层的设计模式——从Script、Code Behind到MVC、MVP、MVVM》(转)_第3张图片

2、视图(View)将数据层现给用户。一般的视图都只是包含用户界面(UI),而不包含界面逻辑。比如,Asp.net中包含控件的页面(page)就是一个视图。视图可以从模型中读取数据,但是不能修改或更新模型。
3、层现器(Presenter)/控制器(Controller)包含了根据用户在视图中的行为去更新模型的逻辑。视图仅仅只是将用户的行为告知控制器,而控制器负责从视图中取得数据然后发送给模型。

MVC/P模式的核心是为了将模型从视图/控制器中分离出来,从而使得模型独立于它们,因此模型不包含对视图和控制的引用。


什么是MVC(Model View Presenter)模式?

1、为了使得视图接口可以与模型和控制器进行交互,控制器执行一些初始化事件
2、用户通过视图(用户接口)执行一些操作
3、控制器处理用户行为(可以用观察着模式实现)并通知模型进行更新
4、模型引发一些事件,以便将改变发告知视图
5、视图处理模型变更的事件,然后显示新的模型数据
6、用户接口等待用户的进一步操作

这一模式的有一下几个要点:
1、视图并不使用控制器去更新模型。控制器负责处理从视图发送过来的用户操作并通过与模型的交互进行数据的更新
2、 控制器可以和视图融合在一块。Visual Studion中对Windows Forms的默认处理方式就是这样的。【译注:比如我们双击一个Button,然后在它的事件里写处理逻辑,然后将处理的数据写回模型中。这里处理逻辑时 间应该是控制器的功能,但是我们并没有专门写一个控制器来做这件事情而是接受了VS的默认处理方式,将它写在Form的代码中,而这里的Form在MVC 中它就是一个View。所以这说vs默认的处理方式是将把控制器和视图融合在一起的。】
3、控制器不包含对视图的渲染逻辑(rendering logic)

“主动—MVC”模式,也是通常意义下的MVC模式

【译 注:为什么说是主动的?View不是等Controller通知它Model更新了然后才从Model取数据并更新显示,而是自己监视Model的更新 (如果用观察者模式)或主动询问Model是否更新。前面那种等待Controller通知的方式是下面所介绍的“被动—MVC”的实现方式。】

“被动—MVC”模式
与主动MVC的区别在于:
1、模型对视图和控制器一无所知,它仅仅是被它们使用
2、控制器使用视图,并通知它更新数据显示
3、视图仅仅是在控制器通知它去模型取数据的时候它才这么做(视图并不会订阅或监视模型的更新)
4、控制器负责处理模型数据的变化
5、控制器可以包含对视图的渲染逻辑

MVP模式

与“被动—MVC模式”很接近,区别在于“视图并不使用模型”。在MVP模式中视图和模型是完全分离的,他们通过Presenter进行交互。
Presenter与控制器非常相似,但是它们也有一些的区别:
1、Presenter处理视图发送过来的用户操作(在MVC中视图自己处理了这些操作)
2、它用更新过的数据去更新模型(在被动MVC中控制器只是通知视图去更新过的模型中去取新的数据,而主动MVC中模型通知视图去更新显示,控制器不需要做工作)
3、检查模型的更新(与被动MVC一样)
4、(与MVC的主要区别)从模型中取数据然后将它们发送到视图中
5、(与MVC的主要区别)将所做的更新告知视图
6、(与MVC的区别)用Presenter渲染视图

MVP的优势

1、模型与视图完全分离,我们可以修改视图而不影响模型
2、可以更高效地使用模型,因为所以的交互都发生在一个地方——Presenter内部
3、我们可以将一个Presener用于多个视图,而不需要改变Presenter的逻辑。这个特性非常的有用,因为视图的变化总是比模型的变化频繁。
4、如果我们把逻辑放在Presenter中,那么我们就可以脱离用户接口来测试这些逻辑(单元测试)


MVP的问题

由于对视图的渲染放在了Presenter中,所以视图和Persenter的交互会过于频繁。

还有一点你需要明白,如果Presenter过多地渲染了视图,往往会使得它与特定的视图的 联系过于紧密。一旦视图需要变更,那么 Presenter也需要变更了。比如说,原本用来呈现Html的Presenter现在也需要用于呈现Pdf了,那么视图很有可能也需要变更。

MVP模式根据 Module,View,Presenter之间的交互,可以分为Passive View(常规MVP)和Supervising Controller 2种。

Passive View模式:


大 家会发现MVP与MVC最大的一个区别就是“Model与View层之间倒底该不该通信(甚至双向通信)。我想这也是目前做这两方面研究的专家所互相争论 的战场。必定各有各的好处和因好处要付出的代价。起码在MVP模式下的Presenter要拥有“绝对权力”。如果没有它,MODEL与View就是两个 孤岛,尽管各有各的地盘(完全解耦),但不会给企业带来什么有用的价值。

所以我这里有一个比喻来形容MVP中的:
Presenter ----就是一个控制欲极强的女人,甚至就连“用什么姿势”,它都要管一管。
当 然日里万机操心多了就会让自己要做的事越来越多,最终它面临的就是该层代码日益庞杂,且书写起来不太方便,必定就连事件绑定这类鸡毛算皮的事都要归它管, 累不累呀。最终我们看到MVP中的View就真的代码轻闲了不少(国企职工嘛),难怪说View只要从相应的[IVIEW]接口下实现相应的属性和一些简 单方法就完事了,而最终调用[IVIEW]接口下的那个视图实例则完全交给了Presenter,这让我想到了MVC中可以支持“自定义模版引擎(最终由 MVC框架来控制使用系统还是自定义的模版引擎)”以及平时大家常挂在嘴边的换肤功能,想到这里多少还真有那么点意思了(精神层面上)。

当然在微软内部对MVP的理解也有所不同,如下面中所说的 Supervising Controller模式和之前大家看到的PassiveView.

MVC,MVP,MVVM之异曲同工

:http://www.cnblogs.com/changxiangyi/archive/2012/07/16/2594297.html

**********************************************************************

当年用tcp返回二进制,就是web,但二进制解析麻烦。
后来搞了tcp返回字符串,就是web,但字符串不通用。
后来搞了一个cgi,在字符串中拼html,但太烦了。
后来搞了一个脚本开发,php,asp,jsp在html模板中写脚本,但代码不好管。
后来搞了一个mvc,把多数脚本写到专门代码中,但不省事。
后来搞了一个模板,把代码写在模板中分离开,但发现和脚本差不多。
后来搞了一个webform,由服务器生成html代码,但性能低。
后来搞了一个ajax,又把界面程序写在javascript中,但代码量大。
后来搞了一个ajax的mvc,把javascript和显示分离,但不实时。
后来又搞了...

**********************************************************************

那么我们就按照大致的历史进程将这些概念进行划分:

  • Script

  • Code Blocks、Code Behind

  • MVC、MVP、MVVM

我们知道的是现实的历史发生顺序并不如上,因为思想都是相似的,比如MVC很早很早就出现了,解释型语言至今基本上也有很多分支而且在互联网时代大行其道。

但我要说的是:不要在意这些细节!

当然了,这是玩笑,我的意思是,这些内容我懒得应该在另外独立的主题探讨,篇幅也有限。



Script

这里脚本的意思不是指当时是用脚本开发,而是像写脚本一样开发。它们都有一个特点:功能单一、管理单一、入口单一

我们最早的程序是汇编,当时的码农的工作是兼职,工作内容是编写一套寿命不长的机器控制指令,有些甚至是命令,比如至今依然保留的Command(亮点自寻):

到后来计算机被用于科学计算等,需求推动了需要更高的开发效率,所以我们有了高级语言。

那个时候码农其实多是数学家,程序的作用很简单,就是执行一些数学计算,类似今天ICPC的一些算法问题,比如Hello World:

main(){    printf("hello,world\n");}

这时候,程序还可以被归结为输入到输出的过程,我们还能去讲讲冯诺依曼模型。

在这个时代,开发是指编写机器指令,甚至都不配用“开发”这个词来描述这项工作。



软件、UI和Markup Language

在那个时代讲UI等于放屁,根本不存在这种概念。但全赖我们有神器——摩尔定律

但我个人认为摩尔定律是不足以让一个敲命令行的时代在几十年间转变成这种各类框架技术架构实践模式的时代,真正推动计算机形成自有的工程学体系的是还有两样东西就是:

  • 人的能力并没有变强,至少没有在同级数下变强。

  • 人类一定会物尽其用

因为人的能力并没有“跟上”机器,所以才会出现各种模式、方法、工具等等来补足人的不足,以最大地透支机器性能。就像我前几天在闪存无聊时突然想到的一句 架构是对客观不足的妥协,规范是对主观不足的妥协

当我们需要机器做的事情多了起来,我们就没办法在一个芯片上解决所有事情,所以才会有冯诺依曼模型、计算机架构,没办法用一台机器解决,所以才要互联网、分布式、云计算。

同样,随着计算机的发展,要做的事情多了,就出现了软件的概念。当“开发”正式化,我们需求的软件就变得:功能繁杂、管理统一、多入口

真正变化的不是客观本质,而是需求。就像这里说的“软件入口”在客观上我们还是只有一个,原理上始终都只有一个启动程序、一个启动代码片段。但“软件的入口”,已经从指代Main函数变成了指代起始UI,用户已经从指代专业人士变成了指代一般消费者,先有软件的需求,才有软件的定义,而需求是在变化的

一个软件需要比当时多几个数量级的代码:

  • 客观上我们没办法做一个能显示所有代码的显示器

  • 主观上我们没办法在超快速滚动中看清所有代码

所以我们需要添加索引、用多个文件组织代码

机器的发展和软件的需求扩大和细化,我们开始出现了用户界面(User Interface)的概念和最适合用于界面的语言——标记语言(Markup Language)。当然,ML不是为UI而生的,它只是十分适合UI,所以才和UI坠入爱河。

因为有了更高UI的需求,所以代码才正式被分化为描述做什么(业务逻辑)和有什么(UI)的两部分,因为我们开发时没办法在两种思维方式下同时工作,开发时的人脑是单线程的。我们所看到的同时进行UI和逻辑开发只不过是我们学会了在两种模式下快速切换,看起来像同时进行,而不是真正的同时进行。同样的情况也发生在不同的代码片段的开发中。

分化的情况除了UI,还发生在方方面面,比如数据操作、UI的对象和样式分离,我们还是继续从UI讲下去吧。



Code Block和Code Behind(其实还有Code Inside,比如onclick="javascript:alert('哎呀我*')")

UI和逻辑分开了两种语言来写,但是它们也要放在同一个项目中,因为它们原本就是要一起工作的。即使是分开,也需要相连,因为这是它们本来要解决的问题。

这时候我们出现的(通常的)解决方案就是Code Block和Code Behind。虽然从时间上似乎Code Block比Code Behind要早,有种感觉就是越新越好,但实质上它们正交替地发展着,因为谁也没办法解决UI和逻辑代码分化后的一个哲学问题——UI和逻辑是一起的,但是它们却不是一起的


Code Block能很好地处理UI和逻辑间在一起的关系,你在同一个地方可以同时维护UI和逻辑:


复制代码
 1@model GM.OA.Finance2.Web.Models.FinancialBase.CurrencyModel 2@{ 3    ViewBag.Title = "EditCurrencyDrawer"; 4    Layout = "~/Views/Shared/_DrawerLayout.cshtml"; 5} 6 7@section styles { 8<link href="/Content/base/table-form.css" rel="stylesheet"/> 9<link href="/Content/base/drawer.bigtitle.css" rel="stylesheet"/>10 }
复制代码


复制代码
<a href="#" class="addcurrency oa-btn" oa-style="green">添加新币别</a><script type="text/javascript">    $(document).ready(function () {        $('.addcurrency').click(function () {            $.oa.drawer.openUrl('AddCurrencyDrawer/', 'addcurrency', {                width: 300            });        });    });</script>
复制代码


Code Behind能很好地处理UI和逻辑各自分开的关系,你可以让UI和逻辑各自做好各自的事情:


<asp:Button ID="RemoveSelectedCurrency_Button" runat="server" Text="删除选中币别" OnClick="RemoveSelectedCurrency_Button_Click"/><asp:Button ID="RemoveAllCurrencies_Button" runat="server" Text="删除所有币别" OnClick="RemoveAllCurrencies_Button_Click"/>
复制代码
 1protectedvoid RemoveSelectedCurrency_Button_Click(object sender, EventArgs e) 2        { 3var currencyId = Currencies_ListBox.SelectedItem.Value; 4            currencyManager.Remove(currencyId); 5        } 6 7protectedvoid RemoveAllCurrencies_Button_Click(object sender, EventArgs e) 8        { 9            currencyManager.RemoveAll();10         }
复制代码


因为存在两种实现方式,所以就存在了对比,因为存在了对比,所以就存在了争论。就像是Java和.NET、PHP和.NET、WebForm和MVC、Mac OS和Windows、iOS和Android、腾讯和所有其他互联网公司,等等。

问题不在哪个更好,而是我们要解决什么问题。当然,这听(ben)着(lai)像(jiu)是客气话了。

真正在UI和逻辑分化后带来的实质问题是:

  • 是按逻辑和UI划分地管理,还是按单界面的事务进行划分地管理

至少UI和逻辑刚分化的时代,在软件上,我们还认为同一项事务是基于同一个UI的一系列操作完成的。

在摩尔定律还持续发挥作用的时候,计算机领域依旧高速发展,所以通常我们还在为一样事物争论、思考、辩证的时候,它已经发生了质变了,不变的只是我们要解决的问题



事务,以及界面、数据、事件、业务

在之前说到过了,当需求变得庞大,解决方案也会变得庞大;当解决方案变得庞大,就会出现细分;当出现细分,就会出现按哪种方式管理的问题

软件从处理一件事务发展到了要处理许多事务,各事务间有包含、顺序、主次等等的关系,变得越来越复杂。因为数据与逻辑庞大了,所以数据与逻辑就分离了,然后事件和业务分离了。

它们的关系已经在我们还理得清之前持续发展而变得更加难理得清,但在一个时间点上,它们UI的领域大致分化成这些原子:

  • 界面

  • 数据

  • 事件

  • 业务

你要细化的话会有更多繁杂的细节,但相信这么写的话争议性比较小。

当一个问题出现一次的时候它是一个问题,当一个问题出现了无数次的时候它会成为历史,当一个问题将会出现无数次的时候,它将需要一个明确的定义和解决方案。

其中,数据的更新和界面的更新这一特殊事件的问题被放大了无数倍,因为它出现了无数次



Model-View-Controller

在ASP还在奋斗的时候WebForm突然到来,正如WebForm还在奋斗的时候MVC突然到来。当然,我这里讲的MVC还是最原始的MVC,因为MVC在我们还在争论的时候已经发展了许多不同分支了

有一点相信大家同意的就是,我们今天讨论争论的MVC、MVP、MVVM、Code Behind等等都源自于职能分化和规划的思想与目的,MVC不是它们的开始,但是一个很好的开始

相信MVC的模型大家很熟悉,也很容易找到,我们这里用一下某百科的图:

《UI层的设计模式——从Script、Code Behind到MVC、MVP、MVVM》(转)_第4张图片

我们可以看到的是,界面被分到了View,数据分到了载体Model上由Model“携带”,业务集中在Controller中,而推动业务的事件由用户与View交互,通过View向Controller发动。

当然,实现由很多种,每种细节上都有不同,所以我才只讲也只能讲大致的MVC。MVC的其中一个缺点便是没有明确的定义,所以不同的实现(比如Struts和ASP.NET MVC)细节上都是不一样的

我们需要知道的是,MVC并不是像上面所说的一些事情那样是一种“必然的”结果,它是一系列必然结果问题中的一种解决方案,而且是不完美的解决方案。我们顺着推理去到一个地方很容易犯的一个错误就是认为路只有这一条而忽视其他可能性(估计这也是导致很多争斗的原因)。另外,我们在讨论一件事物不完美的时候是有一个情境的,所以请不要像“我说它色彩单一,然后你把它涂成彩色后证明我是错的”。

MVC的一般流程是这样的:View(界面)触发事件--》Controller(业务)处理了业务,然后触发了数据更新--》不知道谁更新了Model的数据--》Model(带着数据)回到了View--》View更新数据

这里也不多再陈述MVC的原理、实践等等,因为这就太长篇大论了。



Model-View-Presenter和一些衍生

像我们之前推理的,分化是一种需求的必然结果,但却没有个一个确定的结果,比如Code Behind和Code Block的问题等等。

MVC顺着需求把UI相关的工作分化成了三份,这点经过实践证明无可厚非。但是它们的三角关系却被一些人认为带来了一些问题,或者应该说他们有“更好的”解决方案

在只有Code Behind和Code Block的那个时候维护是很直接的,不是在同一段代码内解决就是在同一个关联的事件上解决。三角关系的问题就是维护问题。在MVC,当你有变化的时候你需要同时维护三个对象和三个交互,这显然让事情复杂化了

我们之前说到,随着摩尔定律,软件的需求不断地变化和变得庞大。随着需求变得庞大的时候,需求变化也变得频繁,这是一个出现了无数次以后也将会出现无数的无数次的一个问题,所以它需要一个解决方案,哪怕它不一定能被解决

为了解决需求变化,从《人月神话》到敏捷到DDD,它不是我们已经解决了的问题,而是我们正在解决的问题。放在UI的模式和MVC上来讲,就是优化或者替代MVC模式,其中之一就是Model-View-Presenter(MVP)模式。

我们先看看两个MVP模式的图:

(图一)

《UI层的设计模式——从Script、Code Behind到MVC、MVP、MVVM》(转)_第5张图片(图二)

两幅图是不同的,但是对MVC的改进的思想却是一样的:切断的View和Model的联系,让View只和Presenter(原Controller)交互,减少在需求变化中需要维护的对象的数量

这种方式很符合我们的期待,因为我们倾向于:

  • 用更低的成本解决问题

  • 用更容易理解的方式解决问题

许多时候并不是一种模式不好,而是因为人没办法执行,比如不容易理解,我们就会选择容易理解的方式。计算机依赖摩尔定律用数量的增长来解决问题,而人是用方式的改变来解决问题的。同样因为客观原因我们不善于维护多个对象和多个对象之间的关系,所以我们改变了,或者说简化了这种方式。

MVP定义了Presenter和View之间的接口,让一些可以根据已有的接口协议去各自分别独立开发,以此去解决界面需求变化频繁的问题。上面两图都有接口,不过接口的实现和使用细节不一样,不过思想上是一致的。

在这里要提到的是,事实上,需求变化最频繁的并不一定是最接近用户的界面,但基本可以确定的是,最接近用户的界面是因为需求变化而需要最频繁更改的。当然,如果View如果是API而不是UI,那就另说了。

还有一些用来“解决”MVC这项缺点的比如有:ASP.NET MVC的ViewBag,Cocoa的delegate。它们都为了简化数据更新的问题而存在,包括MVVM。



Model-View-ViewModel

先直接看看Model-View-ViewModel(MVVM)的图:

从图上看是比MVP简单了,更不用说MVC了。个人不认为MVVM是从MVP进化而来,我只觉得这是在MVP之后出现的一种“更好的”UI模式解决方案,但是用MVP来与之对比比较容易说明问题。

ViewModel大致上就是MVP的Presenter和MVC的Controller了,而View和ViewModel间没有了MVP的界面接口,而是直接交互,用数据“绑定”的形式让数据更新的事件不需要开发人员手动去编写特殊用例,而是自动地双向同步。数据绑定你可以认为是Observer模式或者是Publish/Subscribe模式,原理都是为了用一种统一的集中的方式实现频繁需要被实现的数据更新问题

比起MVP,MVVM不仅简化了业务与界面的依赖关系,还优化了数据频繁更新的解决方案,甚至可以说提供了一种有效的解决模式

至此,我们能理解为什么许多人认为MVVM是最好的一种模式,没有之一。但事实上,MVVM也是依赖于我们至今所讲的“特有的情境”

当然,最优雅的也是第一个能作代表的实践就是Windows Presentation Foundation(WPF)了。



Web

之上,我们在模式演变的推论基本上都还是基于桌面软件的,但是过去十年却是互联网的时代。实际上大部分让大家争议的并不是在桌面领域最合适的是那个,而是在Web领域的模式问题,也就是在B/S场景下的问题

当软件离开单机,去到网络的时候,因为场景变了,所以原有的解决方案也变了,不过需求依然是不变的。我们依然要解决的问题是用户交互与数据更新的问题,还有维护等等的问题

当场景变到Web的时候,我们发现MVVM用来做服务端是极其不适用的,至少现在是不适用的。而MVP你提都不用提。为什么呢?因为:

  • 网络资源成本过高

  • 开发成本过高

问大家一个问题,当一个网页的数据更新后,你希望更新用户看到的数据,你会怎么做?

一般情况下,你会:

window.location.reload();

就算你不这么做,用户也会:

F5


就像之前说的,我们会选择更直接的方式解决问题。直接刷新页面的原因是因为这样更直接,更容易解决数据更新的问题。

很多时候你不会愿意为了一个数据更新写一个AJAX,更别说这个AJAX要带来Loading、事件顺序处理、网络问题、异常处理等等,这就是开发成本过高

另一个网络成本过高就更容易解释了,虽然宽带是基本包月的,但也不带这么用的,何况还有移动用户。更主要的原因是,在本地软件,更新数据是一个引用问题,而在网络应用上,这是一个传输问题。传输成本远高于引用成本,引用之上顶多是在本地内存中再进行一次内存拷贝。

这个时候,我们会更倾向于用MVC模式,因为在Web层面,我们更倾向于一次性更新数据



Web的MVVM

所有问题都不是问题,就算有问题也要解决问题。

为什么这个标题下突然冒出这么一句话?我想说的是,需求依旧是不变的,是推动进步的原动力

还有我之前说过,当我们讨论或者争论一个问题的时候,问题的对象已经发生改变了,而且这次是在我们讨论这个问题之前已经发生改变了。

网络资源成本不断下降,相信已经不需要多提及。摩尔定律和相近的一些原理正在发挥着它应用的作用,网络带宽越来越高、相应速度越来越快。

如果传输因为相对成本下降而导致数据传输的成本低于开发人员拒绝客户的成本,那么它就会被实现而不是被拒绝

另外还有一点就是因为技术的进步,技术的资源不断被更大规模地压榨,需求也不断地增长,那么需求始终会增长超过相对不变的开发成本的。比如jQuery的出现解决了很多问题,我们现在更多地去使用AJAX,哪怕很大一部分依然是为了解决网络资源不足的问题;我们会用更多的样式代码而用了相对更少的图片;我们不再那么依赖Flash一类的矢量图解决方案而直接录制视频。

至少上一节我们说到的两个导致大家选用MVC的问题都正在被解决,所以我们有理由相信未来Web不仅仅需要MVC,可能会需要MVVM或其他解决方案。至少我们能理解容易理解为什么前端会出现一些MVVM的框架,比如先驱knockout.js和AngularJs。这些框架本身的好坏就不作讨论了,因为我们讨论的是模式。

在Web上,MVVM的对比对象就不是MVC,而是Code Block

数据即时更新的需求在扩大,但未必有达到一定要用MVVM这一等级的高大上的模式,实际上如果你要更新一个数据,你还是会采取:

$('.notice').html('发送成功!');

因为......我们依然会采取更直接的方式解决问题......

实际上,现在Web MVVM主要并不是用在了Web或者Wap上,而是移动App上。按照前面的说法,只可能是:

  • HTML+JS比原生在一些场景上更适合Native

  • 在移动App上比Web上更适合使用MVVM

哪怕是Native开发,实际上iOS的开发上也是用类似的数据绑定的方式的。这里也不深究了,毕竟我也不算懂iOS。

要说的是,在Web MVVM或者Web的模式上,也就是Web的富应用上,现在还不过是个初期由膨胀的需求推动的阶段重要的不是技术会怎么走,而是需求和客观条件会怎么走

可能Webform会因为高速开发而焕发第二春,它的AJAX的模式也十分满足于简单开发,但似乎大家需要的不是GUI式的网页。



结尾语

我们不一定需要MVVM,但我们一定需要更强大的方式去解决不断膨胀的Web需求。

我们可以预见的是:

  • 会有更强大的浏览器

  • 会有更强大的JavaScript或者框架

  • 会有更加适合的模式

除去客气话的部分,我还是想说,在不同的需求下其实有最适合的解决方案,通常让我们纠结的不是因为哪个解决方案更好,而是我们看到的条件不够多

编译语言当然比解释语言效率高,但考虑到开发和维护成本,JavaScript等始终会大行其道,比如Node.JS、Python;.NET和微软当然很强大,移植.NET到其他平台也很容易,但微软是家有自己商业模式和要赚钱的公司;当然有些实践和技术更好,但其他开发人员会避开甚至否定自己不擅长的东西,大家都喜欢确定的东西;有些技术更强大,但是只是基于特殊的客观条件和需求,如果你想做大,要么创造客观条件,要么把它结合需求......


你可能感兴趣的:(mvc,MVVM,mvp,web层设计模式)