在域驱动设计(DDD)中了解聚合和聚合根的问题

时间:2019-02-18 09:58:54

标签: domain-driven-design aggregate aggregation aggregateroot

我偶然发现了一个问题:“我无法将域模型拆分为聚合根”。

我是DDD的初级开发人员和新手。我真的很想了解它,但有时确实令人困惑。

在这一点上,我想简要描述一下我的域名。

我的目的是为用户提供机会自行创建任何类型的文档。用户可以创建新型的文档。每个新类型均包含其属性。然后,该应用程序的用户可以根据其类型创建具体的文档。用户还可以发送文档以供批准。每种类型的批准流程都不同。

因此,我们有以下模型:

  1. DocumentType / DocumentTemplate-用作基于以下内容的模板 创建了具体文件。它与一对多关系 文档。
  2. DocumentsAttribute-表示文档的属性。 它与DocumentType有很多关系。
  3. AttributeValue-创建具体文档时,它查看 其类型并为属性创建值, 它的类型。与文档和属性的多对多关系。
  4. 文档-代表由用户创建的具体文档。

还有其他模型,但我认为它们没有道理。

如您所知,这里我应用数据模型的实体属性值(EAV)模式。您可以看到显示数据库中关系的diagram

我的问题是:

除了我已经描述的之外,我的模型中还有很多实体。

我认为Document绝对是我的域中的聚合根。因为汇总的诸如ApprovalProcess之类的东西无法生存。

这是第一个问题:

ApprovalProcess包含其步骤。每个步骤都是可变的,因此是一个实体。步骤的状态可以更改。 ApprvalProcess的状态取决于其步骤。在这里,我们有一个业务不变式:“只有批准了所有步骤,才能批准ApprovalProcess。”

我认为它是一个聚合根,因为它具有业务不变性,并且包含无法生存的实体。而且,我们不想允许直接访问其步骤以保持ApprovalProcess的一致性。

我是否误认为ApprovalProcess是聚合根?可能只是一个汇总? 一个聚合根可以作为一部分存在于另一个根中吗?这是否意味着ApprovalProcess只是聚合的,因为Document负责访问其各个部分?但是,当批准ApprovalProcess的步骤时,Document会将操作委托给ApprovalProcess。

例如:

Document doc = new Document(...);
doc.SendForAooroval(); //ApprovalProcess is created.

doc.ApproveStep(int stepId); // Inside the method Document delegates responsibility for approvement to ApprovalProcess.

或者我应该分别离开Document和ApprovalProcess。因此,文档将按身份引用ApprovalProcess。我们有以下情形:

Document doc = documentRepository.Get(docId);
doc.SendForAooroval();// A domain event "DocumentCreatedEvent" is raised.

DocumentCreatedEventHandler:

ApprovalProcess approvalProcess = new ApprovalProcess(event.DocId); // ApprovalProcessCreatedEvent is raised

approvalProcessRepository.Add(approvalProcess);
approvalProcessRepositroy.UnitOfWork.Save(); //commit 

但是,如果ApprovalProcess的状态更改,则Document的状态也会更改。批准流程被批准,然后文档也被批准。另一个词ApprovalProcess是Document状态的一部分。只有这样,我们才能知道文档已获批准。

还有我遇到的最大问题:

DocumentType也是一个聚合根。它由其属性和ApprovalScheme组成。为了使我的解释尽可能简单,我还没有提到ApprovalScheme。 ApporvalScheme也由某些实体组成。这只是DocumentType的批准流程。根据具有Document的DocumentType的ApprovalScheme创建ApprovalProcess。没有DocumentType不能存在ApprovalScheme。一对一的关系。

文档通过标识引用其DocumentType。正确吗?

在开始执行此任务时,我认为DocumentType应该是Document的一部分。

DocumentType有许多文档,但是在我的域中没有任何意义。它不代表DocumentType的状态。 DocumentType可以标记为已删除,但不能删除。

Document和DocumentType是两个不同的聚合根。我说的对吗?

非常感谢您的阅读。非常感谢您的关注和帮助! 对不起,我的英语不好。

1 个答案:

答案 0 :(得分:1)

  

我是否误认为ApprovalProcess是聚合根?可能是   只是总数?一个聚合根可以存在于另一个根中吗   这是一部分吗?

这些问题对我来说毫无意义。集合是一组实体和值对象,其中一个实体是该组的父级。聚合根是聚合的父实体。一种特殊情况是聚合只是一个实体。当然,单独的实体是集合,而实体当然是集合的根。

我认为我将从另一个角度尝试为您的问题建模:作为状态机。

我将ApprovalProcess视为文档遵循的流程,而不是实体。我不知道该过程的流程图,但是我想您所说的“步骤”将是文档在该过程中可以具有的“状态”,并且您需要在各步骤之间进行转换,因此首先创建一个新文档,这是一个开始,并且在文档的整个生命周期中,它都会一步到另一步,直到达到最后一步(例如,已批准的文档)。

因此,文档实体将具有更改其状态的行为。

例如,在Java中,您可以使用枚举实现状态模式(状态机)。