是否允许客户端代码引用非根聚合中的实体?我有一个 Story
(根)、Team
(实体)和 TeamMember
(实体)。我正在尝试确定 AddTeamMember
方法属于 Team
还是 Story
。
我想我的例子有点误导。我真正的问题是客户端代码可以引用聚合中的非根实体吗?
最佳答案
我的意见 - 不应该。引用属于某个聚合的实体意味着您可以在没有完整聚合上下文的情况下对该实体调用方法,如果您允许这样做,您将永远无法确定整个聚合是否有效且一致。
简单的例子:
public class MyAggregateRoot
{
protected MyEntity entity;
public void BuildUpAggregate()
{
ValidateSomeRule();
LoadEntityFromDatabase();
}
public MyEntity MyEntity
{
get
{
VerifySomeOtherRule();
return entity;
}
}
}
如您所见,在通过聚合根构建和检索 MyEntity 时,我们检查了两个验证规则 - 如果您允许客户端直接引用 MyEntity,聚合可能会在客户端检索实体和执行操作之间的时间发生变化它,因此支票将不再有效,但您不会意识到这一事实。换句话说,您的聚合将不一致并且可能无效。
一般来说,在DDD中有一个严格的规则,声明所有对聚合实体的访问都应该从聚合根开始遍历——这个规则正是为了聚合的一致性。
也就是说,您的客户可以引用的是实体的投影 - 一种只读副本,仅包含显示和确定特定操作在当前上下文中是否可用所需的数据。您可以走得更远,将来自一组实体的数据聚合到一个投影中,稍微调整一下,以便根据 UI 的要求进行定制。我发现这项技术非常有用,因为它不允许我的 UI 决定业务领域应该如何建模。
关于c# - 基本聚合问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7097296/