Domain driven design 如何为实体建模';DDD中的当前状态

Domain driven design 如何为实体建模';DDD中的当前状态,domain-driven-design,Domain Driven Design,我正试图抓住DDD背后的想法,并将其应用到我们的一个宠物项目中,我有一些问题,希望在座的人能够回答 该项目是一个文件管理系统。我们的系统处理的两个概念是特定的问题:一个是文档,另一个是文档状态 文档具有许多属性(如标题、作者等)。用户可以在文档的整个生命周期内更改文档的任何属性 文件可能在任何时候处于特定状态,例如新的,正在修订中,修订的,批准的等。对于每个状态,我们需要知道是谁更改了该状态 我们需要能够根据文档状态查询系统。一个示例查询是“获取处于revisited状态的所有文档” “获取用户

我正试图抓住DDD背后的想法,并将其应用到我们的一个宠物项目中,我有一些问题,希望在座的人能够回答

该项目是一个文件管理系统。我们的系统处理的两个概念是特定的问题:一个是
文档
,另一个是
文档状态

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

文件
可能在任何时候处于特定状态,例如
新的
正在修订中
修订的
批准的
等。对于每个状态,我们需要知道是谁更改了该状态

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

“获取用户X已更改其状态的所有文档”

在同一事务中,唯一需要更改
文档
文档状态
的时间是创建
文档
时(创建文档,同时为其指定状态为
新建

对于所有其他时间,用户界面允许更新其中一个,但不能同时更新两个(即,您可以更改文档的属性,如作者,但不能更改其状态),或者您可以更新其状态(从
新建
修订版下
),但不能更新其属性

我认为我们可以安全地考虑到<代码>文档<代码>是一个实体和一个聚合根。

我们对什么是
DocumentStatus
感到困惑。一个选项是使其成为
文档
集合的值对象部分

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

我们还想提到,我们考虑了各种DDD文档中描述的CQR,但我们认为这太麻烦了,特别是考虑到我们需要对
文档状态执行查询


任何提示或想法都会受到欢迎。

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

由于您正在将更多符合条件的数据(如果不是标识的话)组合到其中,并且您也打算查询这些数据,因此在我看来,好像no
DocumentStatus
与另一个类似,所以值对象没有多大意义,是吗

它由

  • 文件
  • 作者
  • 发生的时间

此外,它在前面的<代码>文档状态> /代码>中更具意义(如果您考虑更多的状态而不仅仅是代码>新的< /代码>和<代码> UnthUp修订< /COD>)。p> 对我来说,这显然排除了将

DocumentStatus
建模为值对象的可能性

就状态作为
DocumentStatus
的属性而言,遵循一切都是对象的概念(目前正在阅读David West的对象思想),那么这当然可以建模为价值对象

接着

领域 您说您需要能够看到过去的状态更改,因此状态历史成为一个域概念。一个简单的解决方案如下:

  • 文档
    实体中定义
    状态历史记录
  • StatusHistory
    StatusUpdate
    值对象的列表
  • 状态历史记录
    中的第一个元素始终反映当前状态-确保在创建
    文档
    实体时将初始状态添加为
    状态更新
    值对象

根据状态历史所需的额外逻辑,考虑为历史本身创建一个专用的值对象(甚至实体)。 坚持不懈


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

您是要记录所有状态转换还是只记录当前状态?我们将记录任何状态更改。我们记录新状态、请求者、更改原因和时间戳。因此,每个文档将有多个状态。当前状态将是最后一次输入的状态。确定,但StatusHistory是单独的聚合还是与文档相同的聚合?我这样问是因为除了创建(您必须在同一事务中创建文档和状态历史记录)之外,在所有其他情况下,这两个都会分别更新。我还需要查找哪些属性来确定它们是否属于同一聚合的一部分?这取决于影响
文档和
状态历史的不变量。如果您需要在这两个变量之间强制执行不变量以保持一致,那么它们将合并在一个集合中。只有当它们能够以最终一致的方式协作时,才能将它们分开。@如果我理解得很好,可以通过引入DocumentStatusChanged域事件将它们分开,StatusHistory可以处理该事件并将其转换为StatusUpdate值对象/实体。