深度探讨MVC式Web架构演进多形态发

本文要点导读:

MVC已成为每一代软件开发人员所最早接触到的软件开发原则之一。

MVC应被视为一种通用的架构原则和方法。

MVC三元组件的语义随架构环境的不同而变化。

可将基于HTTP的WebMVC(WMVC)分成三个不同的类别:sWMVC、dWMVC和pWMVC。

随着近期技术的进步,异步且实时观察变化的“事件循环”可用于WMVC应用的实现。

前言

MVC(模型-视图-控制器,Model-View-Controller)最初用于设计和实现狭义的桌面图形用户界面(GUI)应用开发。经典的MVC与面向对象的程序开发方法一样,已成为每一代软件开发人员所最早接触到的软件开发原则之一。虽然MVC对当今的工业界有着如此重要的影响,但是在日益互联计算的时代,很明显MVC的内涵已迷失了其精准性。这在过去20年间对于WUI(Web图形界面,WebGraphicalInterface)开发领域尤其是如此。基于以上原因,本文意在对MVC的起源做概要地阐述之后,进而深入地探讨基于Web的MVC的演进和变化。

在WUI的应用场景下,原始MVC及MVC三元组中成员对象的历史意义和内涵在不断地演变和转变形态。出于消除任何概念上的混淆的考虑,在本文的探讨中将使用“WMVC”一词表示基于Web的MVC式架构模式。大多数技术平台的WMVC特性正处于不断地改进之中,这包括Microsoft的ASP.NETMVC、PHP的Symfony、Python的Django、Ruby的Merb、Java的JSR等。驱动这些平台改进的原则,很大程度上在于JavaScript已可由客户端浏览器运行。此外,不少新的网络协议充实了服务器-客户间的通信。

JavaScript被XMLHTTPRequest赋予新生以来,它就成为WUI开发中情有独钟的技术。在过去的数年内,就有超过二十种基于WMVC的JavaScript应用萌芽发展,其中包括Dojo、Angular、Ember、Backbone和React等。即使不是全部的也是绝大部分的框架都是侧重于客户端组件的交互,对于WMVC视图和控制器的组成对象而言尤其是如此。自然而言,WUI开发方法上的革新再一次引发了针对MVC亦或WMVC的大量讨论。这些讨论时常是十分激烈的,通常侧重于某个特定的方面,或基于某个特定的环境。进而使得MVC(WMVC)衍生出一些主要差异在于控制器对象的变体,其中包括MVA、MVP、MVVM、Flux、Redux和SAM等。这些MVC变体时常被统称为“MV*”,其中的‘*’表示了各变体间的差异主要在于视图和控制器间的交互方式。通常并不将表示现实世界视图对象的模型组件整体地列入考虑中,或仅是在Web应用方案中将模型作为MVC三元组关系里的被动参与者。

自MVC概念于四十多年前被提出以来,MVC模型很有可能已经历了最重要的改变。在本文的探讨中,我们对MVC模型做了一个宽泛的定义,这个定义中涵盖了驻留内存的模型对象(例如记录集对象),还有用于支撑对象的SoR(主数据记录系统,SystemofRecord)中的源数据、源文档、源文件和原始信号,以及所有把它们同步和聚集到一起的过程。模型数据仓库的存储形式已从小型软盘发展到RDBMS和MMDBMS(多模数据库管理系统,multi-modeldatabasemanagementsystem)。早期模型数据仓库是与驻留内存的模型对象共处一处的,这些模型对象是独立存在于各个用户桌面之上的。现在模型数据仓库使用宽带连接、分布式或基于云的系统,其部署可远离域对象。存储在这种外部环境中的数据,可以被企业生态系统的多个系统修改,也可以被消费者应用的数以千计的用户修改。这种使用场景上的根本差异,已经在根本上地改变了模型对象的行为,进而改变了模型对象与MVC三元组中的另两个成员间的通信和交互。

原型MVC

oMVC(原型MVC,OriginalMVC)是由挪威计算机科学家TrygveReenskaug于年提出,当时他工作于著名的XeroxPARC研究中心Smalltalk团队中。在oMVC的概念初步成型后,最初被实现为Smalltalk-80类库的一部分,用于桌面GUI的建立。

在那个时代,桌面应用远非当前这样是日常家居中的常见物品,每个应用需要独立运行于一台机器上,而每台机器的存储是有限的并且是各自独立的。正如在图1中所示,对oMVC模型对象的任何操作都完全由用户行为通过控制器所触发,MVC三元组在受控的环境中进行通信、同步并保持状态。控制器的主要作用是维持用户和系统之间的联系(参见图1)。控制器实现对相关GUI组件的部署,并在屏幕上将这些GUI组件展现给用户。在Win95出现之前的年代中,这是一个具有挑战性的任务,因为当时MS-DOS依然是占据主要地位的操作系统。在oMVC模型中,一旦用户产生了某种动作,例如菜单选取、在输入框中输入、按钮点击等,控制器就会转化这些动作为对应的改变消息,向模型传递这些消息,并对消息进行处理。

图1展示了独立桌面环境中的oMVC。

图1中显示了作为模型的组成部分的本地软盘数据存储。oMVC中控制器和视图具有成对出现的关系,但是模型的改变并不在两者间直接产生通信。控制器和视图知道模型的状态,但是反之并非如此。

一旦模型从控制器获取了变更通知,它并不直接通过调用去更新所涉及的视图。在模型-视图的关系中,变更通知的获取是通过每个独立的参与者之间的相互注册实现。一旦一方发生了变更,就会生成一个事件,对方就会采取相应的动作作为响应。在图1中,视图是附属于模型的,对模型进行观察。一旦控制器触发了模型变更事件,视图必须去确保自身显示也按需更新,以相应地反映出模型的状态。更新模型的通知信号也可由视图自身生成。这种视图与模型之间的观察(或订阅)和通知关系,有助于模型和视图间的解耦,使得多个视图可隶属于同一模型,进而可提供不同的表示。

在图1中值得注意的是,控制器并非直接地改变视图。在Smalltalk社区及其它后续的桌面GUI应用库中,通常将视图和控制器看成一对耦合的对象。视图使用具有特定控制器类型的实例实现预期的响应。为创建所期望的行为,控制器还可以在不同情景中策略性地、动态地切换类型。这样的视图-控制器对可以嵌套于复合层次结构中(如图2A所示)。在该层次结构中的父辈之间、子女之间及父子之间,视图-控制器组件都可以进行交互和通信。很多情况下,层次结构中的每个独立视图-控制器的子女组件仅处理部分的模型对象。此外,从oMVC组合的角度看,模型也可以使用层次结构的形式进行组织,这样MVC三元组作为一个整体构成层次结构中的父子关系,如图2B所示。

图2左图是oMVC的复合表示,右图是PAC(显示-抽象-控制,Presentation-Abstraction-Control)的表示。

总而言之,oMVC设计范例是由一系列的GoF设计模式所组成,尤其是其中包括了观察者模式、策略模式和复合模式。在早期的桌面应用库中,oMVC域架构和模式的设计意图得以保持,即模型组件由应用域对象和数据存储所组成,其中存储多是本地的或是受限的。在oMVC三元组类的行为中,应用域行为的维护和广播起着核心的作用。oMVC的一个关键假设是模型的稳定性,该假设在上世纪七十和八十年代的桌面应用情景中显然是正确的。但是在WMVC领域,模型时常发生改变通常是一种常态。直至近些年,向用户实时广播变更(类似于oMVC所实现的)所需的技术基础才得以实现。

WMVC的分类

具有讽刺意味的是,虽然直到上世纪九十年代,尤其是在Win95出现之后的年代,桌面计算机开始进入普通百姓家并得到普及,但是传统的桌面应用却因为因特网互联的Web应用开始统治了业界而逐渐退居幕后。不同于安装并于运行于终端用户计算机上的桌面应用,Web应用是宿主于远离用户的服务器上,创建了客户-服务器的关系。在本文的其后内容中,我们将浏览器(browser)和客户(client)这两个概念互换使用。根据浏览器和服务器相对于WMVC三元组对象的部署位置和执行方式的不同,可将WMVC明确地分组为:

服务器端WMVC(Server-sideWMVC,sWMVC):所有WMVC的组件位于服务器上,并在服务器上执行。

双重WMVC(DualWMVC,dWMVC):WMVC组件分布于浏览器和服务器之间。通信可由客户或者服务器端发起。

点对点WMVC(Peer-to-PeerWMVC,pWMVC):这种架构中没有集中式服务器。所有WMVC组件位于客户端,在客户端执行。pWMVC可具有自己的沙箱SoR。

服务器端WMV(sWMVC)

在sWMVC模型中,用户使用浏览器作为瘦客户,通过无状态的请求-响应HTTP协议访问应用(如图3所示)。客户向服务器发送HTTP请求或输入内容,接收并显示整个更新的Web页面(或是其它的文档)。一旦页面被加载以后,各页面组件间就很少有交互了,页面成为静止的。

在这种瘦客户-服务器范式的sWMVC架构中,应用SoR版本库外部化为一种集中式环境。它与应用服务器内存中的域对象是相互分离的。服务器和数据版本库都是远离用户浏览器部署的(如图3所示)。SoR存储常常是由一个或多个关系数据库这样的数据源所组成。鉴于数据已经外部化了,带外进程或不同的用户都可对数据进行更新。数据的变更只会从控制器流向模型(参见图3);当SoR中数据被不同的用户或系统改变时,并不向应用服务器发送入站数据变更通知。不同于oMVC,模型及其所关联的视图间不再有任何的直接联系和必要的同步。由于视图不再反映模型的状态,这就需要用户手动地发起新的HTTP请求去同步和刷新视图。因此sWMC中的“s”,也可指代这种WMVC范例的静态(static)或是陈旧(stale)的本质特性。

图3sWMVC范例的一种表示。

图3中显示了由服务器驻留内存的域对象模型(M)外部化而得到的SoR。不同于oMVC,控制器不再与用户交互,而是用于协调模型与视图间的通信。模型数据的变更是单向流动到外部数据存储中的。

WMVC的模型可简述为一种分层架构(如图4所示)。架构的最顶层模型表示了在视图及其相关的控制器这个关系对之间的契约关系。为满足该契约,在处理栈中可包含数个可变的业务逻辑和数据访问组件。该契约用于所有与视图相关信息的连接,其中的信息可能直接来自本地SoR,或是数据云,或是其它真实世界中的数据源,例如探测器和数据提供系统。

图4WMVC模型的示意图。

图4中显示WMVC的组成包括了多个架构层次,以及来自本地或远程可访问环境中的可变数据源。

相对于在oWMVC中的意义和内容(如图3所示)而言,三元组对象间的关系和通信发生了根本上的转变。与控制器在用户和oMVC系统(图1)间所起的作用不同,sWMVC的控制器承担了在更高层级上协调视图和模型的角色(参加图3)。视图和模型间的通信通过控制器发生。用户与视图进行交互,将模型与模型视图关联的行为逻辑包含在控制器中,由控制器负责管理输入、更新模型并产生适当的输出。

Web应用的架构环境与桌面应用的有所不同,对于将MVC引入到早期Web应用架构的设计中,虽然这在本质上忽视了MVC的原生结构。但是这种引入反而接收了MVC模型的基本理念,即将这三个相互作用的、多变责任的对象类进行相互分离是十分重要的。该做法将oMVC范例提升为UI设计中在更加通用层次上的架构原则,增加了对任意类型UI应用的灵活性和可维护性。

sWMVC中通常包含有多种设计模型,其中也包括在oMVC中所使用的设计原则。例如,各个用例的控制器原则和行为可能都是不同的,包括中介者模式、调度者模式、使用状态模式和模板方法模式的策略模式代理等。但是在oMVC中,观察者模式在触发三个对象类型间的通信中起着关键的作用,尤其是当该模式与视图做相关的更新时。在sWMVC实现中,观察者的作用被缩减了。这样导致了sWMVC的静态和陈腐的特征。直至近些年,技术的进展才使得交互式和富Web用户体验成为可能。

双重WMVC(dWMVC)

在Web时代的早期,由于浏览器的普遍使用,为使现有的桌面交互应用支持Web做出了不懈的努力。这些工作的一个成果体现为Microsoft的OutlookWeb项目所研发的一种基于Web的新组件,该组件允许客户端脚本发布异步HTTP请求到服务器。该工作引导了XMLHttpRequest(XHR)协议的建立和标准化。该协议是至上世纪末为止最具有革命性的工作。XMLHTTPRequest随后成为AJAX技术的基本原则。

当前,基于这种技术的架构使得dMWVC的视图-控制器对可以动态分布,并可安装到用户桌面、移动设备或其它设备的浏览器上。浏览器组件与服务器上模型间的异步通信,用于同步给定的或者所有的视图元素的dWMVC三元对象组状态,进而提供给用户对现实世界或模型对象的最新认知。这种技术的引入使得XHR切实地丰富了客户应用,为浏览器用户带来了交互式的用户体验。

XHR技术还引发了单页应用(SPA)开发技术的发展。类似于oMVC应用,SPA是驻留在单一页面上的Web网站,提供了无缝的浏览体验。对于用户而言,SPA看上去在从一个页面到另一个页面时并没有任何页面重载,对不同页面渲染所需的资源是在所需时由幕后的服务器动态且异步加载的。SPA和这种dWMVC应用的交互行为的组合使此类范式划分为了富互联网应用(RIA)的最新条目。

就XHR协议自身而言,从客户端的视图-控制器对象到服务器端模型间的通信依然仅是单向的通信,需要由视图发起某种类型的轮询机制去探测模型上的更改。轮询是一种资源密集型操作,因而成为影响性能的一个







































白癜风初期的治疗方法
云南白癜风治疗



转载请注明:http://www.guyukameng.com/aspnet/2018-08-23/9639.html