activerecord作为模型,这是一个好主意吗?
最近,由于Rails的流行,许多人开始使用ActiveRecord作为模型。但是,在我听说Rails之前(我的同辈小组不喜欢开源的东西,我们在.NET学校教过……),而在我做最后一个项目时,我发现了模型的定义
The model represents enterprise data and the business rules that govern access to and updates of this data. Often the model serves as a software approximation to a real-world process, so simple real-world modeling techniques apply when defining the model.
它并没有说该模型应该像activerecord那样代表一个表。而且通常在一个事务中,可能必须查询几个不相关的表,然后操作来自不同表的数据...因此,如果将activerecord用作模型,则任何一个都必须将所有逻辑代码都塞到控制器中(有点在某些php框架中很流行),这使得很难测试或者破解activerecord模型,因此它不仅在其映射到的表上还对其他相关表执行数据库操作...
那么,作为MVC架构模式中的模型,滥用(IMHO)活动记录有什么好处呢?
解决方案
回答
Martin Fowler在企业应用程序体系结构模式中描述了该模式,以及其他两种模式或者体系结构。这些模式适用于不同的情况和不同的复杂程度。
如果我们只想简单的东西,可以使用事务脚本。这是在许多旧的ASP和PHP页面中看到的体系结构,其中单个脚本包含业务逻辑,数据访问逻辑和表示逻辑。当事情变得更加复杂时,这很快就消失了。
我们可以做的下一件事是在表示和模型之间添加一些分隔。这是activerecord。该模型仍然与数据库绑定,但是我们具有更大的灵活性,因为我们可以在视图/页面/任何对象之间重用模型/数据访问。它不像以前那样灵活,但是取决于数据访问解决方案,它可能足够灵活。 .Net中的CSLA之类的框架在此方面有很多方面(我认为实体框架看起来也有点像这样)。它仍然可以处理很多复杂性,而不会变得难以维护。
下一步是分离数据访问层和模型。这通常需要一个好的OR映射器或者很多工作。因此,并非每个人都想这样走。域驱动设计等许多方法都采用了这种方法。
因此,这完全取决于上下文。我们需要什么,什么是最佳解决方案。有时,我什至仍将事务脚本用于简单的一次性代码。
回答
在MVC中将Rails ActiveRecord用作模型的妙处在于,它为我们提供了自动的ORM(对象关系映射器),并且为创建模型之间的关联提供了简便的方法。正如我们所指出的,有时可能缺少MVC。
因此,对于涉及许多模型的复杂事务,建议我们在控制器和模型之间使用一个Presenter(Rails Presenter Pattern)。演示者将汇总模型和事务逻辑,并将保持易于测试的状态。我们绝对希望努力将所有业务逻辑都保留在模型或者演示者中,并且不包含在控制器中(Skinny Controller,Fat Model)。
回答
我已经说过很多次了,将Active Record(或者几乎相同的ORM)用作业务模型不是一个好主意。让我解释:
PHP是开放源代码,免费的(以及所有漫长的故事...),这一事实为它提供了大量的开发人员社区,可将代码注入论坛,GitHub,Google代码等网站。我们可能会认为这是一件好事,但有时它往往不是那么"好"。例如,假设我们正在面对一个项目,并且希望使用ORM框架来解决用PHP编写的问题,那么……我们将有很多选择:
- 教义
- 推进
- QCodo
- 麻木
- 红豆
这样的例子不胜枚举。定期创建新项目。想象一下,我们已经构建了一个完整的框架,甚至基于该框架的源代码生成器。但是我们之所以没有放置业务类,是因为"毕竟为什么要再次编写相同的类?"。时间流逝,一个新的ORM框架发布了,我们想切换到新的ORM,但是我们必须使用对数据模型的直接引用来修改几乎每个客户端应用程序。
底线,Active Record和ORM应该位于应用程序的数据层中,如果将它们与Presentation Layer混合使用,则会遇到类似我刚才提出的示例那样的问题。
听听@Mendelt的明智话:请阅读Martin Fowler。他投入了大量有关OO设计的书籍和文章,并发表了一些有关OO设计的好材料。另外,我们可能希望研究"反模式",尤其是"供应商锁定",这是当我们使应用程序依赖于第三方工具时会发生的情况。最后,我写了一篇有关同一问题的博客文章,因此,如果需要,请查看一下。
希望我的回答有用。