如何在 DDD 中对实体的当前状态进行建模
How to model an entity's current status in DDD
我正在努力掌握 DDD 背后的想法并将它们应用到我们拥有的一个宠物项目中,我有一些问题希望这里的人能够回答。
该项目是一个文档管理系统。我们遇到的特定问题与我们的系统处理的两个概念有关:Document
和 DocumentStatus
.
的概念
A Document
有许多属性(例如标题、作者等)。用户可以在其生命周期内更改 Document
的任何属性。
A Document
可能随时处于特定状态,例如 NEW
、UNDER_REVISION
、REVISED
、APPROVED
等。对于每个状态,我们需要知道是谁对该状态进行了更改。
我们需要能够根据文档状态查询系统。一个示例查询是 "Get me all documents that are in the REVISED
state".
"Get me all documents whose status has been changed by user X"
唯一需要在同一事务中更改 Document
和 DocumentStatus
的时间是在创建 Document
时(创建文档并同时分配它的状态 NEW
).
对于所有其他时间,UI 允许更新其中一个但不能同时更新两者(即您可以更改文档的 属性,例如作者,但不能更改其状态。)或者您可以更新其状态(从 NEW
到 UNDER_REVISION
)但不更新其属性。
我认为我们可以安全地认为 Document
是实体和聚合根。
我们对 DocumentStatus
是什么感到困惑。一种选择是使其成为 Document
聚合的值 Object 的一部分。
另一种选择是使它成为实体并成为其自身聚合的根。
我们还想提一下,我们考虑过各种 DDD 文档中描述的 CQRS,但我们认为这太麻烦了,尤其是考虑到我们需要对 DocumentStatus
执行查询这一事实.
欢迎任何指点或想法。
如果你只是记录当前状态,那么它很可能是一个值对象。
由于您正在将更多符合条件(如果不是识别)的数据组合到其中,并且您还打算查询这些数据,那么对我来说这听起来好像没有 DocumentStatus
是另一个,所以一个值对象没有多大意义,是吗?
它被识别为
- 文档
- 作者
- 发生时间
此外,它在 previous DocumentStatus
的上下文中更有意义(如果你考虑的状态不仅仅是 NEW
和 UNDER_REVISION
).
对我来说,这清楚地排除了建模 DocumentStatus
作为值对象的可能性。
根据状态作为DocumentStatus
的属性,并遵循一切皆对象(目前正在阅读 David West 的 Object Thinking),那么当然可以将其建模为值对象。
关注 。
域
你说你需要能够看到过去的状态变化,所以状态历史成为一个领域概念。一个简单的解决方案如下:
- 在
Document
实体中定义一个 StatusHistory
。
StatusHistory
是 StatusUpdate
个值对象的列表。
StatusHistory
中的第一个元素始终反映当前状态 - 确保在创建 Document
实体时将初始状态添加为 StatusUpdate
值对象。
根据状态历史记录需要多少额外的逻辑,考虑为历史记录本身创建一个专用值对象(甚至实体)。
坚持
您并没有真正说明您的持久层是什么样的,但我认为每个持久性机制都应该可以针对 StatusHistory
列表的第一个元素创建查询。例如,使用 map-reduce 数据存储,创建一个由 Document.StatusHistory[0]
索引的视图,并使用该视图实现您需要的查询。
我正在努力掌握 DDD 背后的想法并将它们应用到我们拥有的一个宠物项目中,我有一些问题希望这里的人能够回答。
该项目是一个文档管理系统。我们遇到的特定问题与我们的系统处理的两个概念有关:Document
和 DocumentStatus
.
A Document
有许多属性(例如标题、作者等)。用户可以在其生命周期内更改 Document
的任何属性。
A Document
可能随时处于特定状态,例如 NEW
、UNDER_REVISION
、REVISED
、APPROVED
等。对于每个状态,我们需要知道是谁对该状态进行了更改。
我们需要能够根据文档状态查询系统。一个示例查询是 "Get me all documents that are in the REVISED
state".
"Get me all documents whose status has been changed by user X"
唯一需要在同一事务中更改 Document
和 DocumentStatus
的时间是在创建 Document
时(创建文档并同时分配它的状态 NEW
).
对于所有其他时间,UI 允许更新其中一个但不能同时更新两者(即您可以更改文档的 属性,例如作者,但不能更改其状态。)或者您可以更新其状态(从 NEW
到 UNDER_REVISION
)但不更新其属性。
我认为我们可以安全地认为 Document
是实体和聚合根。
我们对 DocumentStatus
是什么感到困惑。一种选择是使其成为 Document
聚合的值 Object 的一部分。
另一种选择是使它成为实体并成为其自身聚合的根。
我们还想提一下,我们考虑过各种 DDD 文档中描述的 CQRS,但我们认为这太麻烦了,尤其是考虑到我们需要对 DocumentStatus
执行查询这一事实.
欢迎任何指点或想法。
如果你只是记录当前状态,那么它很可能是一个值对象。
由于您正在将更多符合条件(如果不是识别)的数据组合到其中,并且您还打算查询这些数据,那么对我来说这听起来好像没有 DocumentStatus
是另一个,所以一个值对象没有多大意义,是吗?
它被识别为
- 文档
- 作者
- 发生时间
此外,它在 previous DocumentStatus
的上下文中更有意义(如果你考虑的状态不仅仅是 NEW
和 UNDER_REVISION
).
对我来说,这清楚地排除了建模 DocumentStatus
作为值对象的可能性。
根据状态作为DocumentStatus
的属性,并遵循一切皆对象(目前正在阅读 David West 的 Object Thinking),那么当然可以将其建模为值对象。
关注
域
你说你需要能够看到过去的状态变化,所以状态历史成为一个领域概念。一个简单的解决方案如下:
- 在
Document
实体中定义一个StatusHistory
。 StatusHistory
是StatusUpdate
个值对象的列表。StatusHistory
中的第一个元素始终反映当前状态 - 确保在创建Document
实体时将初始状态添加为StatusUpdate
值对象。
根据状态历史记录需要多少额外的逻辑,考虑为历史记录本身创建一个专用值对象(甚至实体)。
坚持
您并没有真正说明您的持久层是什么样的,但我认为每个持久性机制都应该可以针对 StatusHistory
列表的第一个元素创建查询。例如,使用 map-reduce 数据存储,创建一个由 Document.StatusHistory[0]
索引的视图,并使用该视图实现您需要的查询。