DDD. 何时在树状结构中使用聚合根?



在有界上下文中,我创建了一个Entity,用作此上下文中其他对象的聚合。问题是,一个Entity的实例可能与另一个Entity处于子父关系中。就数据库而言,这意味着有一个parent_id字段引用同一entities表中的一行。

问题是,从 DDD 的角度来看,是否可以将Entity的实例作为其自己的构造函数的参数?或者最好使用聚合根(或Entity标识符)。那么,哪种方式更好:

class Entity {
public constructor (arg1, arg2, Entity parent) {
...
this.setParent(parent);
}
}

或者这样:

class Entity {
public constructor (arg1, arg2, int parent_id) {
...
this.setParentId(parent_id);
}
}

仅仅因为你有一个类似树的结构并不意味着这个结构中的所有实体都应该是同一个聚合的一部分。

可以将系统设计为将每个实体实例放在其自己的聚合中。由于每个实体都有一个父实体,因此您必须引用此父实体。

  • 一种方法是像您的第一个示例一样使用对象引用

  • 另一种方法是使用按标识引用,如第二个示例所示

如果使用对象引用,则意味着必须从数据库一起加载所有引用的对象。这可能会导致您加载大量它们。如果您的应用程序不需要您这样做,最好避免这样做。

如果选择使用对象引用,则可以像在 ecample 中一样将实体传递给构造函数。

如果使用按 ID引用,则只能加载一个对象,然后如果需要,可以使用 ID 加载另一个对象。如果您希望拥有仅在特定情况下相互需要的多个聚合,并且您不需要一直将它们一起加载,因为您的应用程序不需要您这样做,这将非常有用。

下面是一个示例:

public TreeNode {
public Guid ParentID { get; private set; }
}
public void DoSomethingToNode(Guid nodeId) {
var node = TreeNodeRepository.GetById(nodeId);
var parent = TreeNodeRepository.GetById(node.ParentID);
// do stuff with parent and child.
}

如果你还没有读过DDD的书,我推荐它。

沃恩·弗农(Vaughn Vernon)的这篇文章在聚合建模方面也很棒

最新更新