DDD:如何建模聚合根之间的关联

时间:2017-11-22 06:09:32

标签: associations entity domain-driven-design aggregateroot value-objects

我们有一个聚合根,如下所示。

@AggregateRoot
class Document {
    DocumentId id;
}

客户提供的问题陈述是"文档可以有多个文档作为附件"

因此重构模型将导致

//Design One
@AggregateRoot
class Document {
    DocumentId id;

    //Since Document is an aggregate root it is referenced by its id only
    Set<DocumentId> attachments;

    attach(Document doc);
    detach(Document doc);
}

但是这个模型本身就足够了,因为客户想要存储一些关于附件的元信息,例如谁附加它以及何时附加它。这将导致创建另一个类。

class Attachment {
   DocumentId mainDocument;
   DocumentId attachedDocument;
   Date attachedOn;
   UserId attachedBy;

   //no operation
} 

我们可以再次重构Document模型,如下所示

//Design Two
@AggregateRoot
class Document {
    DocumentId id;
    Set<Attachment> attachments;

    attach(Document doc);
    detach(Document doc);
}

下面给出了我能想到的不同的建模可能性。

  1. 如果我选择设计方法,那么我可以将Attachment类建模为聚合根,并在附加文档时使用事件创建它们。但它看起来不像聚合根。
  2. 如果我选择设计2,那么Attachment类可以建模为值对象或实体。
  3. 或者如果我使用CQRS,我可以使用设计1和模型Attachment作为查询模型,并使用事件填充它。
  4. 那么,这种方案的正确建模方法是什么?有没有其他方法来模仿我提到的其他内容?

1 个答案:

答案 0 :(得分:1)

从长远来看,您可能会发现传递值而不是实体会使代码更易于管理。如果attach / detach不关心整个文档,那么只需传入他们关心的位(也就是接口隔离原则)。

attach(DocumentId);
detach(DocumentId);
  

单独使用这个模型是不够的,因为客户想要存储一些关于附件的元信息,例如谁附加它以及何时附加它。

是的,这很有道理。

  

这是建模此场景的正确方法吗?

提供的信息不足(礼貌地说“它取决于”。)

通常通过查看行为而不是结构或关系来发现聚合边界。附件关系只是一个可以添加/删除的不可变值,还是一个内部状态随时间变化的实体?如果您更改附件,您还需要哪些其他信息,等等。