MVC中的M在哪里?


14

我试图将我的应用程序重构为MVC,但是我坚持使用M部分。

在数据库支持的应用程序中,该模型是在应用程序代码中实现的,对吗?

但是,数据库中有什么-模型也不是吗?

(我没有将数据库用作简单的对象存储-数据库中的数据是企业资产)。


I'm not using the database as a simple object store。我猜这意味着数据库中以存储过程的形式存在一些业务逻辑。从理论上讲,这与MVC背道而驰,但实际上并不重要。
yannis 2011年

@YannisRizos -有 BL的DB,但我的意思是在这个我想在数据库中的数据有自己的生活和意义超越了应用。

3
I want the data in the DB to have a life and meaning beyond the application.什么?
yannis 2011年

2
@YannisRizos-非常感谢您帮助重构该声明。数据是企业资产,对吗?它不属于该应用程序-因此不允许该应用程序创建一些疯狂的非规范化模型,从而使该应用程序变得非常简单,如果这会使重用其他应用程序中的数据变得非常困难。有什么建议么?

1
不会有问题,如果存在任何需要共享的格式,那么它将成为存储格式要求的一部分。将来任何需要其他格式的内容都可以具有ETL任务,也可以在DAL中进行转换。
StuperUser 2011年

Answers:


46

是的,代码和数据库中的模型都是“模型”。

该模型与您的应用程序“ IS”有关,而控制器则与它的“作用”有关。任何直接对数据库进行持久化的代码都被视为模型。

注意: MVC是一种模式,因此请不要考虑过多。让所有人都以正确的方式进行MVC很容易,但是归根结底,这只是一种心态!这意味着将您的业务逻辑放在数据库和UI之外-就是这样。在使用MVC之前,人们会在应该将其放置在服务器上时将所有业务逻辑放到他们的网页中,否则他们将在数据库中触发一堆脚本来执行业务逻辑以及持久性代码。MVC的出现使人们开始以一种有助于使他们的代码可重用的方式开始思考,因此不要过多地关注细节。


15
那么从C和V的角度来看,有一个数据库只是M的实现细节?

绝对是 措辞不错。
herby

3
@MattFenwick从C和V的角度来看,没有数据库。您使用数据库的目的不只是数据存储,用MVC术语来说,数据库只是数据存储。但这完全可以,只要它适合您的应用。
yannis 2011年

5
+1代表“不要过度思考mvc”
哈维尔,

2
“使您的业务逻辑脱离数据库和用户界面”-这
David Murdoch

17

Trygve Reenskaug 于1978年撰写了描述MVC模式的初始论文。他所描述的模型是表示现实世界中的对象,现象和概念的对象模型。在数据库支持的应用程序场景中,模型是数据的投影。简而言之,模型就是您的应用程序所关注的类及其之间的关系。

实际上,MVC中通常使用两种模型,即域模型(映射到您的数据库)和应用程序模型(在今天的术语中也称为视图模型)。应用程序模型是域模型的投影,该模型还包含用于呈现视图的特定于视图的数据。这种方法称为MMVC。控制器直接与域模型进行交互,并向视图提供应用程序模型。在MVVM模式中,将应用程序模型和控制器结合在一起。


+1:我最喜欢这个答案。The model is a projection of your data.该数据库旨在以最有效的方式存储数据,以进行访问和建立索引。该模型应围绕业务领域设计。
乔尔·埃瑟顿

花了我一点时间来解析the Domain Model (what's mapping to your database)。好答案!

2
+1这是对MVC演变成的不同风味的很好描述。
瑞安·海斯

谢谢你们。在写书时,我一直在深入研究这些东西。很高兴有道理!
迈克尔·布朗

3
  1. 您不需要MVC数据库。如果您的模型碰巧与数据库对话,那就太好了。它也可以将自身保留为平面文件,或者完全不保留。

  2. 该模型是数据存储在应用程序的内存中的位置。您还将需要使用该模型对其数据进行计算和验证。例如,您有一个FinancePayment模型,具有诸如利率,期限和本金的属性。您可以在模型中添加getMonthlyPayment()方法以计算每月付款。您不想在控制器或视图中执行此操作。

  3. 该视图应该是愚蠢的,要么完全没有逻辑,要么仅使用简单的数据绑定(请参阅Martin Fowler网站上的Passive View和Supervising Controller模式)。用户进行填充(例如单击按钮)时,该视图引发事件。

  4. 控制器负责处理事件(当用户单击“保存”按钮时运行一些代码),并负责设置模型属性,并告诉模型加载和保存自身(如果使用持久性)。控制器不应对模型数据进行计算。但是,在控制器中,您可以代表视图进行一些计算,例如“如果model.profit()<0则widget.colour ='red'”

  5. 您应该能够切换到应用程序的命令行版本,而无需更改模型,也不会丢失模型的功能。

一种。通过切换视图(而不是控制器或模型),您应该应该能够切换到应用程序的移动版本(而不是桌面版本)。您应该能够在没有GUI测试框架的情况下对模型和控制器进行单元测试。


对!这很清楚。

2

模型是与前端中的V和C以及后端中的持久性存储(可以是文件,也可以是SQL / NoSQL数据库的任何东西)连接的代码。不仅是从db加载并存储到db的代码(这是对模型的误解之一),而且实际上是所有“域”工作的代码-选择,过滤,更改,计算,决定数据。包括应用程序的所有非UI逻辑。


您要保留的原始数据。在最适合您的模型的任何组织中。该模型是使您的应用程序逻辑生效的API。该数据库是(非活动)数据的存储。如果您的应用程序可行(我不知道它是哪种类型的应用程序),请尝试不要将其视为“数据库支持的应用程序”,而只是将其视为使用数据库的一种“应用程序”保留模块数据。许多问题源于“图标化”数据库-它不过是模型的数据存储;您可以抛弃它,对其进行重组,或者在需要时进行更换。
herby

(以上仅适用于未与其他应用程序共享数据库中的数据的情况)
Herby

我为评论中的单词选择不当表示歉意-我的意思是说,对于MVC,我不确定数据库中的内容。数据库是否在MVC之外?它是模型的一部分吗?它是V还是C的一部分(可能不是,但是您明白了)。

我知道了。您可能从我的回答中得出,您可以看到它是模型的一部分,该模型用于保留模型中的代码处理的应用程序数据。(我看到了EDIT):如果该数据库必须超出应用程序的寿命,则应将数据库视为外部服务,该模型必须与之进行通信,获取数据进行计算并发回一些数据。
herby

在极端情况下,当业务逻辑位于数据库本身中时,您可以拥有非常薄的模型,该模型主要中继到数据库,甚至可以说db 您的模型(但随后它应该具有所有逻辑)。
herby

2

采取非常简单和理想的观点。

该模型通常被视为域(大约是业务)的模型,而不是数据的模型。这些可能看起来很相似,但是它们并不完全相互关联。

视图应该是应用程序前端的模型,而控制器应该是从一个视图到另一个视图的流程的模型。

业务逻辑应该完全封装在模型中,无论是在数据库中还是在代码中。尽管在视图或控制器中可能会重复某些业务逻辑,但是由于各种原因,应该可以(并且安全)完全删除这两个组件,并在其位置放置一个不同的前端。


1

据我了解,MVC只是对客户端应用程序体系结构模式的描述。Wikipedia中的图片仅显示以下内容:

http://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller

当然,当您在“存储过程”中实现应用程序的某些部分时,这些数据库代码也可能是模型甚至控制器的一部分(取决于代码的作用)。但是,如果不是这种情况,那么正如您所说的,数据库显然在“ MVC之外”。


1
But then, what is in the database -- is that not also the model?

不它不是。模型管理应用程序域的行为和数据”。通常,模型是连接到数据库的,但绝不是要求。该模型是新的您的应用程序和数据库之间层。后端可以是一组Mock对象,XML或任何其他支持数据持久性的东西。

通过分离各层,您可以为自己提供更大的灵活性,以使用更好的单元测试实践,使代码更易于管理(EG SQL被Oracle取代)以及其他好处。

控制器也是如此。MVC将控制器定义为两层之间的中间人。在MVC中没有定义“业务层”。相反,您添加自己的。MVC并未封装构建大多数应用程序所需的所有层。这只是基本结构的一般指导。

这些分隔是允许控制功能反转的关键。


+1是一个很好且非常有用的答案;虽然,我建议最后一句话应该阐明。IoC不一定广为人知和理解,因此可能会增加一点点混乱。关于您的意思的真正有用的解释可能超出了合理的SE答案的范围,但确实让我惊讶。
亚当·克罗斯兰

但是,如果将业务逻辑放在存储过程中,则可以,数据库确实包含该模型。(个人而言,我不建议您采用这种方法。)
Roy Tinker

1
@Roy Tinker-不,没关系。该模型在概念上是分开的。在该层中某处将存在与数据库集成的实体。这些实体应保持与模型中存在的具有其他关系的其他实体(例如,模拟)分离。控制器应以不知道数据来自何处以及来自何处的方式来调用模型。相反,应该使用依赖项注入和IoC(基本上是一个可以绑定到不同后端,模拟或数据库的接口)来确定。
P.Brian.Mackey 2011年


0

实际上,这非常简单,“模型”代表数据接口的抽象。这就是为什么:

  • 数据库被视为模型的一部分,而不是模型本身
  • 模型的数据可以来自数据库,文件,Web服务,甚至可以被模拟。
  • MVC,HMVC或类似框架中的模型类应存储查询(请参见“胖模型,瘦控制器”原理[ 1 ] [ 2 ] [ 3 ])

而且,如果我是对的,这就是为什么当有人在MVC上下文之外引用模型时,有人最有可能引用数据结构(即schema)的原因。


0

我认为M包含一些逻辑并将数据存储到DB中。控制器调用哪个模块将被执行,该模块将执行逻辑并将数据存储在DB(可能具有持久层)中,然后该模块将值返回给V。


0

MVC中的M(odel)应该在一个地方捕获业务/域的模型

理想情况下,这应该包括域的业务规则及其结构。

理想情况下,C(控制器)只应将自己的业务模型信息中介到演示文稿(例如View),并从V(iew)捕获用户输入以启动模型状态的更改。

数据库层仅处理(或者应该只处理)特定时间点的模型状态持久性。

因此,它不是那种属于要么模型控制器 MVC模式的一部分,而是它是可以隐式地通过透明地坚持任何改变模型来实现(作为正面的功能的完全独立的关注,提供所述与您的模型与控制器之间的交互),或者这样做的频率更高,通常是在控制器完成对模型的更改后由控制器显式调用。


0

理想世界中的模型应该只包含业务逻辑,它可以对某些真实对象(例如房屋)进行建模。但是,在几乎所有情况下,模型都需要将其数据持久保存到某个存储中。

模型和存储的数据之间的交互作用既可以在单独的数据层上发生,也可以直接在模型中发生,这就是使用ORM(对象关系映射器)时的情况。换句话说,模型要么直接连接到数据库,要么将其数据传递给连接到数据库的其他“数据访问”对象。

ORM(对象关系映射器)将数据库表中的字段映射到模型对象的属性,从而提供getter和setter。在这种情况下,没有单独的数据层,并且模型直接负责持久化其数据。

这是一个使用ActiveRecord流行的ORM 的Ruby示例:

class House < ActiveRecord::Base
end

house = House.new
house.price = 120000
house.save

Pricehouses表中的一个字段,可自动检测到该字段,并通过ActiveRecord该字段将吸气剂和设置剂添加到对象。什么时候save被称为价格属性的值保存到数据库。

从我的角度来看,拥有数据层的优点是,您可以在数据到达模型之前对其进行操作,从而减少了对模型的担忧,减少了责任。例如,您可能需要组合来自几个不兼容数据源的数据,这是ORM无法轻松处理的。

主要缺点是它要管理的另一层抽象,如果您不需要它,也不要打扰,请保持简单。更少的活动部件,更少出错。


-1

你是对的。

(模型视图控制器)

用于构建将数据(模型)与用户界面(视图)和处理(控制器)分开的应用程序的体系结构

在实践中,由于MVC视图和控制器是密切相关的,因此它们通常组合为一个对象。根据MSDN

控制器解释用户的鼠标和键盘输入,通知模型和/或 the view to change as appropriate.

检查此图:

在此处输入图片说明

例如,控制器代码验证对数据的请求,并使该请求在视图中返回。视图控制器对象仅与一个模型相关联。然而,a model can have many view-controller objects associated with it.


4
In practice, MVC views and controllers are often combined into a single object because they are closely related.如果您这样做,那说明您做错了...
yannis 2011年

图从哪里来?定义来自哪里?请不要只是在没有适当归因的情况下从互联网复制粘贴内容。
yannis 2011年

@Yannis Rizos-他引用了MS文档。这里有点脱离上下文,但是他们说非Web应用程序通常具有视图/控制器的耦合,但是Web应用程序有非常明显的区别。这可能是您没有看到MS为其Windows应用程序(而不是MVVM)推送MVC的原因之一,而仅仅是Web应用程序。 msdn.microsoft.com/zh-CN/library/ff649643.aspx
P.Brian.Mackey 2011年

1
@ P.Brian.Mackey我怀疑MS背后是某种原因:P
yannis 2011年

我已经编辑了您的答案,以包括提供的链接@ P.Brian.Mackey。引用外部资源是完全可以的,但是您必须包括指向它们的链接。MVVM也可能与MVC非常相似,但模式不同。在MVC中,视图和控制器绝对不能组合成单个对象...
yannis 2011年
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.