真正的MVC是什么?


201

作为一名认真的程序员,您如何回答MVC是什么?

在我看来,MVC是一个模糊的主题,因此,如果您的受众是学习者,那么您可以自由地以不太可能引起争议的通用术语来描述它。

但是,如果您是在与知识渊博的听众(尤其是采访员)交谈时,我很难考虑采取这样的方向,而不会冒“不正确!!”的反应。我们都有不同的实际经验,而且我还没有真正两次遇到相同的MVC实现模式。

具体来说,似乎在严格性,组件定义,零件分离(适合什么地方)等方面存在分歧。

因此,我该如何以正确,简洁和无争议的方式解释MVC


4
注意:如果您使用的是ASP.NET,则MVC具有第二种含义:ASP.NET MVC
Brian

MVC已经在这里很好
smzapp

Answers:


155

MVC是一种软件体系结构-系统的结构-将域/应用程序/业务(无论您愿意使用什么)逻辑与其余用户界面分开。它通过将应用程序分为三部分来实现:模型,视图和控制器。

该模型管理应用程序的基本行为和数据。它可以响应信息请求,响应指令以更改其信息状态,甚至可以在信息更改时通知事件驱动系统中的观察者。它可以是数据库,也可以是任何数量的数据结构或存储系统。简而言之,它是应用程序的数据和数据管理。

该视图有效地提供了应用程序的用户界面元素。它将来自模型的数据呈现为适合用户界面的形式。

控制器接收用户输入,并调用模型对象和视图以执行适当的操作。

总之,这三个组件共同创建了MVC的三个基本组件。


7
+1我真的更喜欢将MVC看作是三个(或更多)模式的体系结构,而不是设计模式。没有规范的实现,它不是那么小,并且所有实现都比隐含的核心组件多得多。
yannis 2011年

51
尽管此答案有21票赞成票,但我发现“这可能是一个数据库,或任何数量的数据结构或存储系统。该模型是纯业务/域逻辑。而且它可以而且应该不仅仅是应用程序的数据管理。我还区分了域逻辑和应用程序逻辑。控制器不应包含业务/域逻辑或直接与数据库对话。
猎鹰

9
我不能完全不同意这个答案,仅仅是因为它声称MVC在表示层之外是合理的。其余的答案都可以。MVC应该在表示层开始和结束,并且绝对不应在其中包含您的业务逻辑和存储库。这样做可以有效地将整个应用程序放置在表示层中,并且不提供任何可用的API,而无需为原始应用程序设计这些API即可直接访问您的业务逻辑或纯数据。尚无扩展性,视图模型使您更接近,但仍缺少松散耦合
Jimmy Hoffa,2012年

6
@Jimmy:在MVC的许多构造中,模型可以在API中重用,因为它们不依赖于UI-视图和模型之间的分隔可解决这一问题。但这当然取决于您如何选择定义“模型”。如果要对MVC做出判断,则应首先说明您使用的是哪种 MVC解释。
Owen S.

5
@Yannis:这只是一个问题:什么是模式架构?您为什么不将其称为另一种设计模式?GoF(和Alexander)对设计模式的定义非常明确,很显然,模式不应该规定一种规范的实现(尽管两本书的普及都削弱了这一概念)。
Owen S.

135

比喻

我这样向父亲解释了MVC:

MVC(模型,视图,控制器)是一种用于组织应用程序中的代码以提高可维护性的模式。

想象一个摄影师在工作室里用他的相机。一位顾客要他拍一张盒子的照片。

盒子是模型,摄影师是控制器,相机是视图

由于包装盒不了解照相机或摄影者,因此它是完全独立的。这种分隔使摄影者可以绕着箱子走动,并以任意角度对准照相机以获取所需的拍摄/观看效果。

非MVC架构倾向于紧密集成在一起。如果盒子,控制器和摄像机是一个相同的对象,那么每次我们想要获得新视图时,我们都必须拉开然后重新构建盒子摄像机。另外,拍照总是像尝试自拍照一样-并非总是那么容易。


详细说明

只是在阅读了以下邮件列表问题/答案后,我才觉得自己了解MVC。引用:https : //mail.python.org/pipermail/python-list/2006-January/394968.html

布瓦哈写道:

作者引用wxPython中的mvctree.py作为MVC设计的示例。但是我还是太环保了,所以我发现那个特定的例子太复杂了,我不理解作者建议的分离。

MVC完全是关注点分离。

该模型负责管理程序的数据(私人数据和客户数据)。视图/控制器负责为外界提供与程序的客户端数据进行交互的方式。

该模型提供了一个内部接口(API),以使程序的其他部分能够与之交互。视图/控制器提供了一个外部接口(GUI / CLI / Web表单/高级IPC /等),以使程序之外的所有内容都可以与其通信。

该模型负责维护程序数据的完整性,因为如果该数据损坏了,那么每个人都将面临失败。视图/控制器负责维护UI的完整性,确保所有文本视图都显示最新值,禁用不适用于当前焦点的菜单项,等等。

该模型不包含任何视图/控制器代码;没有GUI小部件类,没有用于布置对话框或接收用户输入的代码。视图/控制器不包含模型代码;没有验证URL或执行SQL查询的代码,也没有原始状态:小部件保存的任何数据仅用于显示目的,仅反映了存储在模型中的真实数据。

现在,这里是对真正的MVC设计的测试:即使没有附加View / Controller,该程序在本质上也应该具有完整的功能。好的,外界将很难以这种形式与之交互,但是只要知道适当的Model API规定,程序就会像往常一样保存和操作数据。

为什么会这样呢?好吧,简单的答案是,这全归功于Model和View / Controller层之间的低耦合。但是,这还不是全部。整个MVC模式的关键是这些连接的发展方向:所有指令都视图/控制器流向模型。模型从不告诉视图/控制器要做什么。

为什么?因为在MVC中,虽然允许视图/控制器对模型(特别是模型的API)有所了解,但不允许模型对视图/控制器有任何了解。

为什么?因为MVC是要创建明确的关注点分离。

为什么?为了防止程序复杂性突然失控并把您(开发人员)埋在其中。程序越大,该程序中的组件越多。这些组件之间存在的连接越多,开发人员维护/扩展/替换单个组件的难度就越大,甚至很难遵循整个系统的工作原理。问问自己:在查看程序结构图时,您是希望看到树还是猫的摇篮?MVC模式通过禁止循环连接来避免后者:B可以连接到A,但是A不能连接到B。在这种情况下,A是模型,而B是视图/控制器。

顺便说一句,如果您很敏锐,您会注意到刚才描述的“单向”限制存在问题:当甚至不允许模型时,模型如何将模型用户数据的更改通知视图/控制器知道视图/控制器,没关系向它发送消息吗?但是不用担心:有一个解决方案,即使一开始看起来有些round回,它也很整洁。我们待会儿再讲。

实际上,一个View / Controller对象可以通过模型的API,1.告诉模型做事(执行命令),以及2.告诉模型给它做事(返回数据)。视图/控制器层 将指令推送到模型层,并从模型层提取信息

这就是您的第一个MyCoolListControl示例出问题的地方,因为该类的API要求将信息 送到其中,因此您又回到了各层之间的双向耦合,违反MVC规则并将您直接转回到您最初想避免的cat摇篮架构。

相反,MyCoolListControl类应随流程一起使用,并在需要时从下面的层中提取所需的数据。对于列表窗口小部件,通常意味着先询问有多少个值,然后依次询问每个项,因为这是最简单,最松散的方法,因此将耦合最小化。而且,如果该小部件希望以很好的字母顺序将这些值呈现给用户,那么这就是其普及性;及其责任,当然。

现在,有一个难题,正如我之前指出的那样:在基于MVC的系统中,如何使UI的显示与模型的状态保持同步?

这就是问题所在:许多View对象都是有状态的,例如,复选框可能被打勾或未打勾,文本字段可能包含一些可编辑的文本。但是,MVC规定所有用户数据都存储在“模型”层中,因此,由其他层保留的用于显示目的的任何数据(复选框的状态,文本字段的当前文本)因此必须是该主“模型”数据的辅助副本。但是,如果模型的状态发生更改,则该状态的视图副本将不再准确,需要刷新。

但是如何?MVC模式可防止模型将该信息的新副本推入View层。哎呀,它甚至不允许模型向View发送消息,说明其状态已更改。

好吧,差不多。好的,不允许Model层直接与其他层进行通信,因为这样做需要它知道有关这些层的某些信息,而MVC规则可以阻止这种情况。但是,如果一棵树落在森林中而周围没人听见,它会发出声音吗?

您看到的答案是建立一个通知系统,为Model层提供一个可以向任何人宣布的地方,尤其是它刚刚做了一些有趣的事情。然后,其他层可以在该通知系统中发布侦听器,以侦听他们实际上感兴趣的通知。它只是发布公告,然后忘记它。而且,如果有人听到了该公告,并且想在事后做某件事(例如向模型询问一些新数据,以便可以更新其屏幕显示),那就太好了。该模型仅列出其API定义中发送的通知。其他人对这些知识所做的一切都取决于他们。

MVC被保留,每个人都很高兴。您的应用程序框架可能会提供一个内置的通知系统,否则,您可以编写自己的通知系统(请参阅“观察者模式”)。

...

无论如何,希望能有所帮助。一旦您了解了MVC的动机,就可以以某种方式完成事情的理由变得有意义,即使乍一看它们似乎比必要的情况复杂。

干杯,

拥有


MVVM和
MVCS

86

MVC通常一个流行词。

它曾经被认为是一种模式,但是其最初的1979年定义却被愚弄,遗忘,误解,脱离了原始语境。它的定义一直很模糊,以至于它开始类似于一种宗教,虽然这无疑有助于其货运主义者捍卫它,但它的名称已不再与一套可靠的指导方针联系起来。因此,它不再真正被视为一种模式。

MVC从未打算描述Web应用程序。
既没有现代操作系统,也没有语言。
(其中一些人实际上使1979年的定义多余了)

做到了。而且没有奏效。

现在,我们处理一个淫秽的Web-MVC混合动力,它的流行语状态恶劣,定义不清,并且以半文盲的程序员作为目标人群,因此对整个软件模式的宣传确实非常糟糕。

因此,MVC成为了那些不想真正考虑太多的人的关注点分离

  • 数据模型的处理方式之一,
  • 视图中的另一个,
  • 其余的仅被命名为“控制器”,并由读者自行决定。

上世纪90年代的网站/ Web应用程序并没有真正使用关注点分离。

它们是混杂的意大利面条代码的可怕缺陷。
UI的更改,重新设计和数据重新整理非常困难,昂贵,耗时,沮丧,命运多.。

诸如ASP,JSP和PHP之类的Web技术使得将视图关注点与数据以及应用程序关注点混合在一起非常容易。刚进入该领域的新手通常会发出与旧时代一样不可分割的代码泥潭。

因此,越来越多的人开始在支持论坛上无休止的循环中重复“使用MVC”。人数增加到包括经理和营销人员的程度(从某种意义上说,在gui编程的那个时代,这个词就已经很熟悉了,在这种情况下这种模式才有意义),这成为了我们现在必须面对的流行语的庞然大物。

就目前而言,这是常识,而不是方法论
这是一个起点,而不是解决方案
这就像告诉人们呼吸空气,或紧缩,而不是治愈癌症


22
这当然不是主要是一个时髦词。的确,MVC比其他设计模式更普遍,更不那么独特,因此您可以将其视为组织原则或范例。但是无论您怎么说,它都是许多非常成功的面向对象框架中的基本概念。假装这只是一个时髦的词,即一个时髦的短语,意义不大,这是对OP的损害。
Caleb

23
It's a fancy word for pre-existing concepts that didn't really need one.哪种设计模式/架构不符合该描述?
yannis 2011年

8
+1坦率地说,一旦您掌握了基础知识(内聚性,耦合性,可读性,正统性等)并将其与现代语言的功能相结合,这些东西中的大多数就显而易见了。
lorean 2011年

12
The data model is handled one way, the view in another, the rest is just named "controller"+1
c69 2012年

33
-1。我希望所有愚蠢的+1评论能得到-10。给定耦合和内聚的基本原理,这种“显而易见的”情况如何?UI架构比比皆是,包括MVC,MVP,MVVM,Forms和Smalltalk的模型。一些公司还将WS-CAF等应用程序的体系结构推向了极致。说“常识”会自动将您带到MVC,这与笛卡尔所谓的上帝证明一样多。显然,这是您所知道的,但是您的答案表明您对其他方法的无知或无法扩大自己的视野。
亚罗诺(Aaronaught)2012年

39

定义它的最好方法是查阅曾发明它的Trygve Reenskaug的原始著作:http : //heim.ifi.uio.no/~trygver/themes/mvc/mvc-index.html

特别是通常认为该文件为定义性文本:http : //heim.ifi.uio.no/~trygver/1979/mvc-2/1979-12-MVC.pdf

楷模

模型代表知识。模型可以是单个对象(而不是有趣的东西),也可以是对象的某种结构...

一方面,模型与其零件之间应存在一对一的对应关系;另一方面,模型所有者应感知到所代表的世界。因此,模型的节点应代表问题的可识别部分。

模型的节点都应处于同一问题级别,将面向问题的节点(例如,日历约会)与实现细节(例如,段落)混合在一起是令人困惑并且被认为是不好的形式。

意见

视图是其模型的(视觉)表示。通常,它将突出显示模型的某些属性,而抑制其他属性。因此,它充当表示过滤器

视图被附加到其模型(或模型部分),并通过提出问题从模型中获取表示所需的数据。它还可以通过发送适当的消息来更新模型。所有这些问题和消息都必须使用模型的术语,因此视图必须知道其代表的模型的属性的语义。(例如,它可能会要求提供模型的标识符并期望使用Text的实例,但可能不会假定模型属于Text类。)

控制器

控制器是用户与系统之间的链接。它通过安排相关视图以在屏幕上的适当位置显示自己,从而为用户提供输入。它通过向用户呈现菜单或其他提供命令和数据的方式,为用户提供输出方式。控制器接收这种用户输出,将其转换为适当的消息,然后将这些消息传递到一个或多个视图。

控制器从不应该补充视图,例如,它不应通过在节点之间绘制箭头来连接节点的视图。

相反,视图从不应该了解用户输入,例如鼠标操作和击键。应该总是有可能在控制器中编写一个方法,该方法将消息发送到视图,这些视图精确地重现任何用户命令序列。

编辑

控制器已连接到其所有视图,这些视图称为控制器的各个部分。一些视图提供了一个特殊的控制器,即编辑器,该控制器允许用户修改视图提供的信息。这样的编辑器可以被拼接到控制器及其视图之间的路径中,并将充当控制器的扩展。完成编辑过程后,将编辑器从路径中删除并丢弃。

请注意,编辑器通过所连接视图的隐喻与用户进行通信,因此该编辑器与该视图紧密相关。控制器将通过询问视图来获得编辑器的权限-没有其他合适的来源。


11

MVC是一种用于隔离业务逻辑与表示的设计模式。

它与许多其他设计模式的不同之处在于,它通常不是很简洁地实现,而是框架的基础。

尽管实现策略模式的应用程序只是其中的一小部分细节,但说Web应用程序使用MVC设计模式非常定义其体系结构


2
这不是严格有用的,实现MVC模式有非常特定的要求,这使其与MVP,MP,MVVM不同。它的目标受众也不同于其他演示模式。
伊恩

8

MVC是将系统或子系统的以下组件分开的软件设计:

  1. 模型-有关应用程序或其组件状态的数据。可能包括用于修改或访问的例程。
  2. 视图-数据(模型)的解释。这仅限于视觉表示,而可以是音频,派生信息(例如,将统计信息传递到另一个模型对象中)等。此外,单个模型可能具有多个视图。
  3. 控制-处理对系统的外部输入,以调用模型上的修改。控件/视图可能紧密相关(在UI的情况下)。但是,可以处理完全独立于视图的其他外部输入(例如网络命令)。

6

我会说MVC是一个概念或一系列相似的模式。

我认为这篇文章值得一读。Martin Fowler的GUI架构


5
Fowler的文章非常出色,每个使用MVC术语的人都应该阅读它。我发现特别有趣的两点是,术语MVC在GUI中的原始用法与Web框架中的用法大不相同,并且在GUI中,发现视图和控制器之间的分隔没有预期的有用。
汤姆·安德森

3

首先,您必须确定问题的提出者是谁,以及他正在寻找什么样的答案。您用另一个问题来回答这个问题,例如“从什么意义上说?”。

您可以询问他们是否一般来说是指MVC,MVC的特定实现(即asp.net MVC,spring MVC,smalltalk MVC等),从技术上讲,它在哲学上是什么(是的,它具有以及哲学等)。

如果这是测试中的问题,并且您无法要求要求者澄清,那么您将不得不根据上下文进行猜测。

一个简单的好答案是:

MVC是一种软件用户界面体系结构,用于分离结构和行为方面的问题,以简化软件的可维护性。

您还可以说:

通过将视图与控制器与模型分离,它鼓励根据组件的职责来隔离组件。从理论上(通常在实践中),这可以通过防止系统的不同部分混合并创建更复杂的系统来帮助提高可维护性。

但是,最后,将判断您是否提供他们期望的答案。解决该问题的唯一方法是找出他们期望的答案。


2

这就是我要说的。我会尝试用移动应用程序来解释它,因为它是我最熟悉的,并且因为我认为在开始做移动应用程序之前我并不完全了解它。
让我们以Android为例。
表示层,即。可以(应该,通常是)完全在xml中指定用户界面。为了简单起见,假设一个xml文件描述了应用程序中的一个屏幕。XML文件指定控件,控件的布局,位置,颜色,大小,字符串标签...有关表示的所有内容。然而,对于何时调用它,何时将其放置在屏幕上一无所知。它是独立布局还是更大布局的一部分?在那里,您可以找到:完美的VIEW

现在,显然在某个时候需要在屏幕上放置视图,那么该怎么办呢?您的CONTROLLER在Android中称为Activity。顾名思义,活动就是一些活动。即使其唯一目的是显示在步骤1中定义的视图,它也将执行某些操作。因此,活动获取一个视图并将其显示在屏幕上。由于视图对活动一无所知,因此,活动对实际表示一无所知。我们(程序员)可以多次重新排列视图的布局,而无需在活动中甚至更改一行代码。

现在,在没有实际执行任何操作的情况下,呈现漂亮的,定义明确的xml布局并没有太大用处。假设我们要存储用户输入的数据。活动需要解决这个过程,从用户获取数据到将数据传递给其他人进行处理(处理,存储,删除)。它会传递给谁?好,到一个模型。我喜欢将模型视为纯模型。对它所处的应用程序上下文一无所知的java类。(实际上,情况永远不会如此)。

假设我有一个Person类,它具有三个属性:名称,地址,年龄。我的XML定义的布局具有3个字段供用户输入:名称,地址,年龄。我的活动从用户输入中获取三个值,创建一个新的Person对象,并在其上调用一些方法,该方法知道如何处理某些Person特定的逻辑。你有它。模型视图控制器。


1

我总是从告诉他们这个模式不是什么新东西开始,并且已经存在很多年了……在这一点上,他们给了我一个好奇的外观和BAM !,他们迷上了:

然后,我将像前面的答案一样谈论各种问题,但是我认为同样重要的是上下文相关,正如JB King所说的,ASP.NET MVC等,

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.