【问题标题】:How to model an entity's current status in DDD如何在 DDD 中建模实体的当前状态
【发布时间】:2024-01-21 19:46:01
【问题描述】:

我正在努力掌握 DDD 背后的想法,并将其应用到我们拥有的一个宠物项目中,我有一些问题希望这里的人能够回答。

该项目是一个文档管理系统。我们遇到的特殊问题与我们的系统处理的两个概念有关:Document 的概念和 DocumentStatus 的概念。

Document 有许多属性(例如标题、作者等)。用户可以在 Document 的整个生命周期内更改任何属性。

Document 可能在任何时候处于特定状态,例如 NEWUNDER_REVISIONREVISEDAPPROVED 等。对于每个状态,我们需要知道是谁进行了该更改那个状态。

我们需要能够根据文档状态查询系统。示例查询是“获取所有处于REVISED 状态的文档”。

"获取所有状态已被用户 X 更改的文档"

DocumentDocumentStatus 需要在同一事务中更改的唯一时间是在创建Document 时(创建文档并同时为其分配状态NEW) .

对于所有其他时间,UI 允许更新其中之一但不能同时更新(即您可以更改文档的属性,例如作者,但不能更改其状态。)或者您可以更新其状态(从 NEW 到 @ 987654336@) 但不是它的属性。

我认为我们可以安全地考虑 Document 是一个实体和一个聚合根。

我们对DocumentStatus 是什么感到困惑。一种选择是使其成为 Document 聚合的值对象的一部分。

另一种选择是使其成为实体并成为其自身聚合的根。

我们还想提一下,我们考虑过各种 DDD 文档中描述的 CQRS,但我们认为这太麻烦了,特别是考虑到我们需要对 DocumentStatus 执行查询这一事实。

欢迎任何指点或想法。

【问题讨论】:

  • 您是要记录所有状态转换还是只记录当前状态?
  • 我们将记录任何状态变化。我们记录新状态、请求人、更改原因和时间戳。因此,每个文档会有多个状态。当前状态将是最后输入的状态。

标签: domain-driven-design


【解决方案1】:

你说你需要能够看到过去的状态变化,所以状态历史变成了一个领域的概念。一个简单的解决方案如下:

  • Document 实体中定义StatusHistory
  • StatusHistoryStatusUpdate 值对象的列表。
  • StatusHistory 中的第一个元素始终反映当前状态 - 确保在创建 Document 实体时将初始状态添加为 StatusUpdate 值对象。

根据状态历史记录需要多少额外的逻辑,考虑为历史记录本身创建一个专用的值对象(甚至实体)。

持久性

您并没有真正说明您的持久层是什么样子,但我认为每个持久性机制都应该可以针对StatusHistory 列表的第一个元素创建查询。例如,使用 map-reduce 数据存储创建一个由 Document.StatusHistory[0] 索引的视图,并使用该视图来实现您需要的查询。

【讨论】:

  • 好的,但是 StatusHistory 是在单独的聚合上还是与文档在同一个聚合上?我之所以问,是因为除了创建的情况(您必须在同一事务中创建文档和状态历史记录)之外,在所有其他情况下,两者都是单独更新的。我还需要寻找哪些其他属性来确定它们是否属于同一聚合的一部分?
  • 这取决于影响DocumentStatusHistory 的不变量。如果您需要在两者之间强制执行不变量以保持一致,则将它们合并为一个聚合。仅当它们能够以最终一致的方式协作时才将它们分开。
【解决方案2】:

如果您只是记录当前 状态,那么这很可能是一个值对象。

由于您要在其中编写更多符合条件的(如果不是标识)数据,并且您还打算查询这些数据,那么在我看来,好像没有 DocumentStatus 是另一个,所以值对象不会很有道理,是吗?

标识
  • 文档
  • 作者
  • 发生的时间

此外,在 previous DocumentStatus 的上下文中它更有意义(如果您考虑的状态不仅仅是 NEWUNDER_REVISION)。

对我来说,这显然排除了将 DocumentStatus 建模为值对象的可能性。

state 作为DocumentStatus 的属性而言,并遵循 everything is an object 的概念(目前正在阅读 David West 的 Object Thinking),那么它当然可以建模为一个值对象。

关注How to model an entity's current status in DDD

【讨论】:

    最近更新 更多