23

我是新手,所以请耐心等待。我最近在几个项目中使用了一个 MVC 框架,一段时间后,我对 MVC 中“模型”的感知有用性感到失望。

我得到了控制器和视图的用处,我知道表示和逻辑之间的分离对于使代码在未来更易于维护很重要,尽管不一定更快或更健壮。

如果所有逻辑首先都应该放在控制器中,我看不到模型有任何用处,尤其是 Active-Record。我们已经有了一种强大且易于使用的语言来与数据库进行通信,对吗?它被称为 SQL。对我来说,当模型像活动记录一样实现时,它的有用性取决于您是否希望您的应用程序适合多个数据库。

所以我要问的是,如果你只使用一个数据库,为什么还要使用 Models 和 Active-Records?为什么不只使用 SQL?为什么要增加额外的复杂性?你们有任何案例研究/现实生活中的故事,模型实际上可以比仅使用数据库类和 SQL-away 做得更好吗?

再次,如果我看起来如此无知,我很抱歉,但我真的不知道为什么模型很重要。谢谢回答。

4

5 回答 5

21

首先,您假设模型层必须使用某种 ORM,以便将 SQL 抽象掉。这不是真的:您可以创建一个模型层,它与控制器层松散耦合,但与特定 DBMS 紧密耦合,因此避免使用功能齐全的 ORM。

有一些 ORM 库,例如 Hibernate (Java)、NHibernate (.NET)、Doctrine (PHP) 或 ActiveRecord-Rails (Ruby),它们确实可以为您生成所有实际的 SQL 语句;但是如果你认为 ORM 是不必要的,并且你想手动定义所有的 SQL 语句,就不要使用它们。

尽管如此,恕我直言,这并不意味着您应该将所有与数据库相关的逻辑都放在控制器层中。这被称为“胖控制器”方法,它多次导致臃肿、无法维护的代码。您可以将它用于简单的 CRUD 项目,但除此之外的任何事情都需要存在真正的“模型”。

你似乎关心 MVC。请阅读有关 TDD 的内容。一位智者曾经说过“遗留代码是未经测试的代码”。当您了解到自动化单元测试与“真实”代码一样重要时,您就会明白为什么企业应用程序中有这么多层,以及为什么您的模型层应该与控制器分开。试图做所有事情(表示、业务逻辑、数据持久性)的代码块根本无法轻松测试(也无法顺便调试)。

编辑

“模型”是一个有点模糊的术语。根据您从哪里看,它可能意味着略有不同。例如,PHP e Ruby 程序员经常将其用作Active Record的同义词,这是不准确的。其他一些开发人员似乎认为“模型”只是某种DTO,这也是不对的。

我宁愿使用Wikipedia中看到的模型定义:

MVC 的中心组件,模型,根据问题域捕获应用程序的行为,与用户界面无关。模型直接管理应用程序的数据、逻辑和规则。

因此,模型是大多数 MVC 应用程序中最大、最重要的层。这就是为什么它通常分为子层:域、服务、数据访问等。模型通常通过域公开,因为在那里您可以找到控制器将调用的方法。但是数据访问层也属于“模型”。任何与数据持久性业务逻辑相关的东西都属于它。

于 2011-02-23T16:59:32.127 回答
9

在大多数现实生活中,来自用户的数据不会直接进入数据库。

它必须经常被验证、过滤或转换。

模型层的作用通常是通过执行这些操作确保数据正确到达后端存储(通常是数据库),这不应该是控制器(瘦控制器,胖模型)的责任,而不是责任数据库引擎本身。

换句话说,模型层负责——或“知道”——应该如何处理数据。

大多数现代 MVC 框架都提供了在数据有效性要求上指定合同的方法,例如 Rails。

这是来自http://biodegradablegeek.com/2008/02/introduction-to-validations-validation-error-handling-in-rails/的示例:

class Cat
  validates_inclusion_of :sex, :in => %w(M F), :message => 'must be M or F'
  validates_inclusion_of :vaccinated, :in => [true,false]
  validates_inclusion_of :fiv, :in => [true,false]
  validates_inclusion_of :age, :within => 1..30
  validates_each :weight do |record, attr, value|
      record.errors.add attr, 'should be a minimum of 1 pound' if value and value  /^[01][0-9]\/[0-9]{2}\/[0-9]{4}$/
  validates_length_of :comment, :allow_blank => true, :allow_nil => true, :maximum => 500
end

这里,一些数据有效性要求不能由数据库处理,也不应该在控制器中处理,因为对这些要求的任何修改都可能在几个地方破坏代码。

因此,模型是确保数据与您的领域一致的最佳场所。

关于它还有很多话要说,但我想解决一个对我来说似乎很重要的问题,受实践经验的启发:)

于 2011-02-23T16:58:18.547 回答
8

这根本不是一个无知的问题!只是你问它而不是简单地忽略整个 MVC 理论并随心所欲地做这个事实很好。:-)

回答您的问题:从概念上讲,模型只是为您的数据提供了一个很好的抽象。模型可以让您思考“我的应用程序的对象如何相互关联,它们如何交互以及我如何从他们那里获取我需要的数据”。

就像视图和控制器帮助您将表示与逻辑分开一样,模型帮助您将应用程序的逻辑(无论如何从用户的角度来看)与数据实际来自何处以及如何在内部表示的细节分开。

举一个更具体的例子(如果不完全现实的话):理论上,您可以编写整个应用程序,以通过 SQL 查询获取所有数据。但后来你意识到你想使用一些 noSQL(CouchDB 等)引擎,因为你需要水平扩展。

使用模型(当然还有一个可以使用这两种存储类型的框架:-))您不必担心细节,因为您的所有重要数据已经通过您的模型以及视图和视图以通用方式表示控制器可以对该表示采取行动。

如果没有它们,您可能必须重写大量代码才能使您的数据获取适应新的后端。

这只是在无聊的存储部分。使用纯 SQL,定义应用程序对象(即业务逻辑)之间的交互要困难得多,因为您不会在 SQL 中这样做(可能,无论如何)。

这不是一个完美的解释(远非如此),但我希望它有所帮助。

于 2011-02-23T16:59:06.433 回答
3

模型应该包含你所有的逻辑。控制器只负责与用户交互相关的逻辑。所有与域相关的功能(所谓的“业务逻辑”)都应该放在模型中并与控制器代码分离。像这样,您可以更好地分离关注点和代码可重用性。

例如,假设您正在编写一个应用程序,让用户输入有关他们自己的信息并接收饮食建议。

一方面,您可以将与转换用户提供的数据相关的代码放入模型部分的饮食建议列表中。这包括数据库访问,还包括与所讨论的问题(问题域)相关的任何计算、算法和处理。

另一方面,您将用于登录用户、显示表单、收集表单数据、验证它的代码放在控制器中。例如,通过这种方式,您可以稍后将 api 添加到您的应用程序(它使用不同的代码进行身份验证、从用户获取数据、验证等)并重用代码来生成结果(来自模型)。

这只是该模型的优点的一个示例。

于 2011-02-23T16:54:12.223 回答
1

我总是将模型与数据联系起来,而不管它在哪里出现或如何表示。在 MVC 中,V 显示数据,C 处理更改。即使您在控制器内的 HashMap 中将所有数据显示在屏幕上;该 HashMap 将被称为模型。

于 2011-02-23T16:47:16.513 回答