Domain driven design 持久性应该是域对象的职责吗?(你能对这篇文章发表评论吗?)

Domain driven design 持久性应该是域对象的职责吗?(你能对这篇文章发表评论吗?),domain-driven-design,Domain Driven Design,我读了一本书 在源代码中,实体对象执行所有CRUD操作。这意味着实体对象直接从方法调用存储库 评论指出: 持久性绝对是域对象的责任 这是正确的吗?“持久性是一个基础结构方面,域层应该与之解耦”:我引用了你提到的文章 持久性由存储库实现处理。域对象应该不知道自己属于这样的存储库 在回答你的问题时,我可以说没有正确或错误的做法,但这种说法是有争议的。如果您的项目以一致的方式进行,并且您对该方法没有意见,那么这可能是一种最佳实践。在我看来,域对象应该不知道持久性问题,因此从纯粹的DDD视图来看,该语句

我读了一本书

在源代码中,实体对象执行所有CRUD操作。这意味着实体对象直接从方法调用存储库

评论指出:

持久性绝对是域对象的责任

这是正确的吗?

“持久性是一个基础结构方面,域层应该与之解耦”:我引用了你提到的文章

持久性由存储库实现处理。域对象应该不知道自己属于这样的存储库


在回答你的问题时,我可以说没有正确或错误的做法,但这种说法是有争议的。如果您的项目以一致的方式进行,并且您对该方法没有意见,那么这可能是一种最佳实践。在我看来,域对象应该不知道持久性问题,因此从纯粹的DDD视图来看,该语句是错误的。

在我看来,作者倾向于使用活动记录模式。我不确定DDD是否严格禁止使用活动记录,但我不会使用它


有关Active Record和DDD共同存在的问题的详细介绍,请参见。

他的论点是实体对象应该不仅仅是数据载体

他认为,实体的所有逻辑都应该在该实体中,而不是将一些实体逻辑放在DAO层,将更多的逻辑放在业务层

这当然有一些好处。例如:

public class Parent {
    @Lazy
    private List<Children> children;
}
公共类父类{
@懒惰的
私人名单儿童;
}
在代码中,从数据库中获取父级。过了一会儿,你决定和孩子们做点什么。在DAO世界中,DAO框架必须以某种方式在某个地方注入一个隐藏字段,该字段允许
getChildren()
从数据库中获取父级的子级

如果该字段是父项的一部分,那么它的工作原理就很明显了

业务逻辑也是如此:如果您更改了实体中的某些内容,那么您必须查找将其用作业务逻辑一部分的所有位置,并确保更改不会破坏任何内容。如果所有业务逻辑都在实体中,这将更简单

不幸的是,OO语言不会出现这种情况。主要的问题是,每个实体中都有太多的代码,对于某些代码,根本不清楚它属于哪个实体。设想一些业务逻辑从输入实体读取数据并将其写入输出实体。这些代码属于哪个实体?输入还是输出


OO根本不允许将这些问题分割成可消化的部分。

如果你阅读了这些评论,你会看到作者解释说,这篇文章主要是为了演示DI技术,而不是促进良好的DDD设计。评论中讨论的源代码有几个好问题。所以,在使用它作为参考之前,你最好三思而后行

为了回答您的问题,通常不建议让实体使用存储库接口,尤其是持久性实现。我会将其与“goto”用法联系起来-这可能是需要的,但您通常不会期望在代码中看到它


我还可以补充一点,如果不将域对象绑定到存储库,那么使用域对象会容易得多。例如,您可以毫不费力地构建FitNesse(验收)测试,而不会干扰数据库或处理实体对存储库的调用。单独使用域对象越容易越好。

如果不阅读本文,我可以说我永远不会将数据访问层作为域对象的一部分来编写

域对象是应用程序中最敏感的部分之一,因为它们在所有应用程序层中都被使用。如果有一天您想更改持久层,那么将持久性逻辑放在其中会给您带来很多麻烦


此外,使用这些对象的大多数代码应该对它们被持久化的事实漠不关心。

作者后来在评论中说:域对象除了封装业务域实体和业务逻辑的状态和行为外,还应该负责持久化数据(CRUD)。通过这种方式,客户端可以直接调用域对象来创建和操作域状态,而不是依赖DAO(我认为是与基础设施相关的类)来处理持久性。。。实体并不总是需要为CRUD函数调用存储库。我明白作者的观点,如果你同意这种方法,这是一种有效的方法,但在我看来,社区并不认为这是主观和有争议的,因为OP试图获得理解,不要强加于人。