【问题标题】:Active Record must have domain logic?Active Record 必须有领域逻辑?
【发布时间】:2013-09-04 01:37:33
【问题描述】:

我开始使用 Yii 框架有一段时间了,我看到了一些“不要让我睡觉”的东西。这里谈谈我对 Yii 用户如何使用 Active Record 的疑惑。

我看到很多人直接在Active Record中添加应用程序的业务规则,同样是Gii生成的。我深信这是对什么是 Active Record 的误解,违反了SRP

Early on, SRP is easier to apply. ActiveRecord classes handle persistence, associations and not much else. But bit-by-bit, they grow. Objects that are inherently responsible for persistence become the de facto owner of all business logic as well. And a year or two later you have a User class with over 500 lines of code, and hundreds of methods in it’s public interface. Callback hell ensues.

当我和一些人谈论它时,我的观点受到了批评。但是当被问到时:

当您需要通过 Gii 重新生成充满业务规则的 Active Record 时,您会怎么做?改写?复制和粘贴?太好了,恭喜!

得到了答案,只有沉默。

所以,我:

为了达到更好的架构,我目前正在做的是在文件夹 /ar 中生成 Active Record。并在 /models 文件夹中添加域模型。

顺便说一下,拥有业务规则的是领域模型,是使用活动记录来持久化和检索数据的领域模型,这就是数据模型。

您如何看待这种方法? 如果我在某个地方错了,请在严厉批评之前告诉我原因。

【问题讨论】:

    标签: php oop design-patterns activerecord yii


    【解决方案1】:

    本文中的一些 cmets 很有帮助: http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

    特别是,您的模型应该在您需要更多时从严格的“胖模型”设置中发展出来的想法似乎非常明智。

    您现在遇到问题还是主要是想提前计划?这可能很难提前计划,并且可能只需要随时重构......

    编辑:

    关于moveUserToGroup(在您下面的评论中),我可以看到它会给您带来怎样的困扰。在我思考您的问题时发现了这一点:https://gist.github.com/justinko/2838490 您可能用于moveUserToGroup 的等效设置将是CFormModel 子类。它使您能够进行验证等,但可以更具体地针对您要处理的内容(并使用多个 AR 对象来实现您的目标,而不仅仅是一个)。

    我经常使用CFormModel 来处理具有多个 AR 对象的表单或我想做其他事情的表单。

    听起来可能就是您所追求的。此处提供更多详细信息: http://www.yiiframework.com/doc/guide/1.1/en/form.overview

    【讨论】:

    • 我现在的问题是我的活动记录是自动生成的。所以,如果我把域规则放进去,当我重新生成这些规则时,这些规则就会丢失。此代码生成不是合并,是删除文件并创建新文件。而且我需要不断地这样做,因为数据库中的实体一直在变化。
    • 两个问题。 1) 你看过 GiiX 的工作方式吗?可能对您的重建有益。 2) 你考虑过改造你的架构吗?在您的模型中具有 no 逻辑将严重阻碍您的长期发展。您的模型中通常需要 一些 逻辑 ...
    • 1) 没有。但是,我会看看。 2) 是的。我完成了我的问题:您如何看待这种方法。
    • 补充:困扰我的是有一个 User 类,例如方法 Relations() 和 moveUserToGroup($group)。听起来它们是完全不同的东西。从面向对象的角度来看,这是正确的吗?
    • 看起来很合理。您可能想要查看的其他项目是 Yii 组件。我们发现它们非常有用,您可以构建可插入的版本(您可以将主要项目换成子类 - 例如 Yii DB 组件)。它们非常强大。
    【解决方案2】:

    根据 Martin Fowler 对 Active Record 的定义:

    一个对象同时携带数据和行为。这些数据大部分是持久的,需要存储在数据库中。 Active Record 使用最明显的方法,将数据访问逻辑放在域对象中。这样,所有人都知道如何在数据库中读取和写入数据。

    当您分离数据和行为时,您不再拥有 Active Record。两种常见的相关模式是 Data Mapper 和 Table/Row Gateway(这一种与 RDBMS 更相关)。

    福勒又说:

    Data Mapper 是一层软件,可将内存中的对象与数据库分开。它的职责是在两者之间传输数据,并将它们彼此隔离。使用 Data Mapper,内存中的对象甚至不需要知道是否存在数据库;他们不需要 SQL 接口代码,当然也不需要数据库架构知识。

    再说一遍:

    表数据网关包含用于访问单个表或视图的所有 SQL:选择、插入、更新和删除。其他代码调用它的方法来与数据库进行所有交互。

    行数据网关为您提供与记录结构中的记录完全一样的对象,但可以使用您的编程语言的常规机制进行访问。数据源访问的所有细节都隐藏在这个界面后面。

    数据映射器通常是独立于存储的,映射器从存储中恢复数据并创建映射对象(Plain-old objects)。映射对象对存储在其他地方一无所知。

    正如我所说,TDG/RDG 更内在地与关系表相关。 TDG 对象表示表的结构并实现所有常用操作。 RGD 对象包含与表的单行相关的数据。与 Data Mapper 的映射对象不同,RDG 对象有良心认为它是整体的一部分,因为它引用了它的容器 TDG。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-09-26
      • 1970-01-01
      • 2011-04-21
      • 1970-01-01
      • 2012-05-27
      • 2014-02-24
      • 2016-12-06
      相关资源
      最近更新 更多