在另一个存储库中使用一个存储库

Using one Repository Inside Another

我是 DDD 的新手,我有一个包含用户引用的合作伙伴聚合。 用户对象本身是另一个聚合。

由于并非所有用户都必须在合作伙伴对象中引用,因此用户对象是一个聚合根。 合作伙伴也是聚合根。

首先: 如果一个聚合根包含在另一个聚合根中,我的设计会不会出错?

第二个: 如果设计是正确的,那么在另一个存储库中使用一个存储库来持久化合作伙伴是否是一种不好的做法? (PartnerRepository 内的 UserRepository)

观察:我没有使用任何 ORM 框架。

First: Would my design be wrong with one aggregate root inside another?

我怀疑。例如,User 可以是某个名为 user management 的域的聚合根,UserProfile 可以是另一个名为 user profiles 的域的聚合根,两个域对象之间可能应该有一个 1:1 关联。

Second: If the design is right, would it be a bad practice to use one Repository inside another to persiste the Partner? (UserRepository inside PartnerRepository)

您应该确保关注点明确分离,并遵循单一职责原则。也就是说,一个存储库可以处理单个领域对象,并且将一个存储库注入另一个存储库打开了处理相关或不相关领域对象的大门。

我的建议是您应该在域服务中表示事务,并且您可以在其中注入所需数量的存储库。

I am new to DDD...

我将从 DDD 的角度回答这个问题,而不是 OOP(面向对象编程)。

First: Would my design be wrong with one aggregate root inside another?

它不会遵循领域驱动设计的一般准则。如果你想从一个聚合根引用另一个聚合根,你可以通过 id 引用它。

Second: If the design is right, would it be a bad practice to use one Repository inside another to persiste the Partner? (UserRepository inside PartnerRepository)

同样,如果遵循 DDD 的指导方针,您将不会这样做,您将使用单独的存储库分别保留每个聚合。

Here's a link to an article by Vaughn Vernon,可能是 DDD 领域第二伟大的人物,解释得更好。

First: Would my design be wrong with one aggregate root inside another?

是的。

AGGREGATE A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the aggregate, designated as the root. A set of consistency rules applies within the aggregate's boundaries.

Eric Evans, Domain Driven Design

您的设计面临的问题是:如果允许用户聚合独立修改相同状态,则合作伙伴聚合无法保护自己的不变量。

当在您的设计中断言 X 是一个聚合时,您是在提出两个声明

  1. 无需咨询任何外部状态即可确定对 X 的任何更改的有效性。
  2. 无需咨询 X 的状态即可确定任何外部更改的有效性。

这就是聚合边界——外改不用看内,内改不用看外。

因此嵌套聚合是矛盾的

表达相同想法的另一种方式:如果一个聚合根在另一个聚合根中,那么您有一个聚合(合作伙伴聚合),它有 两个 根(合作伙伴实体,和用户实体),这正是聚合模式旨在避免的情况。

可能的补救措施:

一个是用户实体确实是合作伙伴集合的一部分。对用户的每次更改都应该由合作伙伴管理。您将用户移回合作伙伴聚合,并阻止您的实现访问它,除非向聚合根发出命令。

另一个是用户 entity 不是合作伙伴集合的一部分。然后你删除合作伙伴中的直接引用;这可能意味着完全消除引用(如果 Partner 的业务规则根本不依赖于用户),或者引用用户标识符,以及检查标识符的业务规则 without 之后(换句话说,您的规则可能会检查 id 引用是否 null/not null,或 is/is 不是集合的成员)。如果您考虑一下,合作伙伴聚合甚至无法判断它引用的用户 是否存在 .

第三个是在您的模型中发现了一个新实体,其中包括合作伙伴聚合实际用于验证的用户部分。这可能是用户状态的快照,也可能是将用户重构为多个部分。