我们有一个聚合根,如下所示。
@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);
}
下面给出了我能想到的不同的建模可能性。
Attachment
类建模为聚合根,并在附加文档时使用事件创建它们。但它看起来不像聚合根。Attachment
类可以建模为值对象或实体。Attachment
作为查询模型,并使用事件填充它。那么,这种方案的正确建模方法是什么?有没有其他方法来模仿我提到的其他内容?
答案 0 :(得分:1)
从长远来看,您可能会发现传递值而不是实体会使代码更易于管理。如果attach / detach不关心整个文档,那么只需传入他们关心的位(也就是接口隔离原则)。
attach(DocumentId);
detach(DocumentId);
单独使用这个模型是不够的,因为客户想要存储一些关于附件的元信息,例如谁附加它以及何时附加它。
是的,这很有道理。
这是建模此场景的正确方法吗?
提供的信息不足(礼貌地说“它取决于”。)
通常通过查看行为而不是结构或关系来发现聚合边界。附件关系只是一个可以添加/删除的不可变值,还是一个内部状态随时间变化的实体?如果您更改附件,您还需要哪些其他信息,等等。