将 Rails 视为 MVC 设计模式的主要内容可能不是最好的主意。所述框架存在一些固有的缺点(我在另一篇文章中对此进行了详细阐述),而社区直到现在才开始解决后果。您可以将 DataMapper2开发视为第一个主要步骤。
一些理论
给出这种建议的人似乎受到了一个非常普遍的误解的困扰。因此,让我首先澄清一下:在现代 MVC 设计模式中,模型不是类或对象。模型是一层。
MVC 模式背后的核心思想是关注点分离,其中的第一步是表示层和模型层之间的划分。就像表示层分解为控制器(实例,负责处理用户输入)、视图(实例,负责 UI 逻辑)和模板/布局一样,模型层也是如此。
模型层由以下主要部分组成:
领域对象
也称为域实体、业务对象或模型对象(我不喜欢后一个名称,因为它只会增加混乱)。这些结构就是人们通常错误地称为“模型”的东西。他们负责包含业务规则(特定领域逻辑单元的所有数学和验证)。
存储抽象:
通常使用数据映射器模式实现(不要与滥用此名称的ORM混淆)。这些实例的任务通常是从域对象中存储和检索信息。每个域对象可以有多个映射器,就像有多种存储形式(DB、缓存、会话、cookie、/dev/null)一样。
服务:
负责应用程序逻辑的结构(即域对象之间的交互以及域对象与存储抽象之间的交互)。它们应该充当表示层与模型层交互的“接口”。这通常是在类 Rails 代码中最终出现在控制器中的内容。
在这些组之间的空间中也可能存在几种结构:DAO、工作单元和存储库。
哦……当我们(在网络环境中)谈论与 MVC 应用程序交互的用户时,它不是人类。“用户”实际上是您的网络浏览器。
那么神器呢?
控制器应该与服务交互,而不是使用一些可怕的单体模型。您将数据从用户输入传递到特定服务(例如MailService
或RecognitionService
)。通过这种方式,控制器改变了模型层的状态,但它是通过使用清晰的 API 来完成的,并且不会弄乱内部结构(这会导致抽象泄漏)。
此类更改可能会立即引起一些反应,或仅影响视图实例从模型层请求的数据,或两者兼而有之。
每个服务都可以与任意数量(尽管通常只有少数)域对象和存储抽象进行交互。例如,RecogitionService
对文章的存储抽象不太关心。
结束语
通过这种方式,您可以获得可以在任何级别进行单元测试的应用程序,具有低耦合(如果正确实现)并且具有清晰易懂的架构。
不过,请记住:MVC 不适用于小型应用程序。如果您正在使用 MVC 模式编写留言簿页面,那么您做错了。此模式用于在大规模应用程序中执行法律和秩序。
对于使用 PHP 作为主要语言的人,这篇文章可能是相关的。这是对模型层的更长描述,带有一些代码片段。