我是新手,所以请耐心等待.我最近在几个项目中使用过一个MVC框架,过了一段时间,我对MVC中"模型"的感知功能感到失望.
我得到了控制器和视图的有用性,我知道表示和逻辑之间的分离对于使代码在未来更易于维护是很重要的,尽管不一定更快或更强大.
如果首先将所有逻辑放在控制器内部,我看不到Model的任何用途,尤其是Active-Record.我们已经有了一种非常强大且易于使用的语言来与数据库进行通信,对吗?它叫做SQL.对于我来说,当实现模型像活动记录时,它的用处取决于您是否希望您的应用程序适合多个数据库.
所以我要问的是,如果你只使用一个数据库,为什么还要使用模型和Active-Records呢?为什么不只使用SQL?为什么额外的复杂层?你们有没有任何案例研究/现实生活中的故事,其中模型实际上可以比仅使用数据库类和SQL-away更好地做事情?
再一次,如果我似乎如此无知,我很抱歉,但我真的不知道为什么模型很重要.谢谢回答.
首先,假设模型层必然使用某种ORM,以便抽象出SQL.事实并非如此:您可以创建一个模型层,该模型层从Controller层松散耦合但紧密耦合到特定的DBMS,因此避免使用功能齐全的ORM.
有一些ORM库,如Hibernate(Java),NHibernate(.NET),Doctrine(PHP)或ActiveRecord-Rails(Ruby),它们可以为您生成所有实际的SQL语句; 但如果您认为ORM是不必要的,并且您想要手动定义所有SQL语句,请不要使用它们.
不过,恕我直言,这确实不是意味着你应该只需将控制器层内的所有你DB相关的逻辑.这被称为"胖控制器"方法,它是一条多次导致臃肿,无法维护的代码的道路.您可以将它用于简单的CRUD项目,但除此之外的任何事情都需要存在真正的"模型".
你似乎关心MVC.请阅读有关TDD的内容.聪明人曾经说过" 遗留代码是没有测试的代码 ".当您了解到自动化单元测试与"真实"代码一样重要时,您就会明白为什么企业应用程序中有这么多层,以及为什么您的模型层应该与Controller分开.尝试执行所有操作的代码块(表示,业务逻辑,数据持久性)根本无法轻松测试(也无法通过调试).
编辑
"模型"是一个有点模糊的术语.根据您所看到的位置,它可能意味着略有不同.例如,PHP e Ruby程序员经常将它用作Active Record的同义词,这是不准确的.其他一些开发人员似乎认为"模型"只是某种DTO,这也是不对的.
我宁愿使用维基百科中的模型定义:
MVC的核心组件(模型)根据其问题域捕获应用程序的行为,与用户界面无关.该模型直接管理应用程序的数据,逻辑和规则.
因此,模型是大多数MVC应用程序中最大,最重要的层.这就是为什么它通常分为子层:域,服务,数据访问等.模型通常通过域公开,因为在那里您可以找到控制器将调用的方法.但是数据访问层也属于"模型".任何与数据持久性和业务逻辑相关的东西都属于它.
这根本不是一个无知的问题!只是事实上你要求它而不是简单地忽略整个MVC理论而且随心所欲地做就好了.:-)
回答你的问题:从概念上讲,模型只是为你的数据提供了一个很好的抽象.模型不是考虑"我如何编写这个内部联接以获得我需要的所有字段",而是让您根据"我的应用程序的对象如何相互关联,它们如何交互以及如何进行交互"来思考从他们那里得到我需要的数据".
与视图和控制器帮助您从逻辑中分离表示的方式相同,模型可以帮助您从应用程序的逻辑(从用户的角度来看)分离数据的详细信息,以及数据实际来自何处及其在内部的表示方式.
给出一个更具体的例子(如果不是完全真实的):理论上,你可以用你通过SQL查询获取所有数据的方式编写整个应用程序.但后来你意识到你想要使用一些noSQL(CouchDB等)引擎,因为你需要水平扩展.
使用模型(以及可以使用两种类型的存储的框架,当然:-)),您不必担心细节,因为所有重要数据都已通过模型和两个视图以通用方式表示.控制器可以根据该表示行事.
没有它们,您可能不得不重写大量代码,以使您的数据获取适应新的后端.
这只是在无聊的存储部分.使用纯SQL,定义应用程序对象(即业务逻辑)之间的交互要困难得多,因为您不会在SQL中执行此操作(可能,无论如何).
这不是一个完美的解释(远非它),但我希望它有所帮助.
在大多数现实生活中,来自用户的数据不会直接进入数据库.
它必须经常被验证,过滤或转换.
模型层的作用通常是通过执行这些操作来确保数据正确地到达后端存储(通常是数据库),这不应该是控制器(瘦控制器,胖模型)的责任,而不是责任数据库引擎本身.
换句话说,Model层负责 - 或者"知道" - 应该如何处理数据.
大多数现代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
这里,数据库无法处理几个数据有效性要求,不应在控制器中处理,因为这些要求中的任何修改都可能会破坏几个地方的代码.
因此,该模型是确保数据与您的域一致的最佳位置.
关于它还有很多话要说,但我觉得要抓住一个对我来说很重要的一点,并以实践经验为动力:)