Domain driven design 应用命令后调用交叉聚合计算函数更新读取模型

Domain driven design 应用命令后调用交叉聚合计算函数更新读取模型,domain-driven-design,cqrs,domain-events,Domain Driven Design,Cqrs,Domain Events,我是CQRS的新手,在我的设计中需要以下情况的建议。命令更新聚合A的状态;因此,需要使用交叉聚合计算方法的结果更新读取模型;该方法属于另一个骨料B,其中包含对骨料a的引用;该方法是聚合B和引用聚合a状态的函数。调用此函数的正确位置在哪里 我的注意事项(可以跳过): 命令处理程序更新聚合A的状态可以从存储库中获取聚合B,对其调用计算并将结果放入域事件中;然而,我相信,除了一个被修改的聚合之外,获取聚合不是命令处理程序的工作,即使是为了读取目的;另外,命令处理程序的任务不是执行计算,只是发送事件,

我是CQRS的新手,在我的设计中需要以下情况的建议。命令更新聚合A的状态;因此,需要使用交叉聚合计算方法的结果更新读取模型;该方法属于另一个骨料B,其中包含对骨料a的引用;该方法是聚合B和引用聚合a状态的函数。调用此函数的正确位置在哪里

我的注意事项(可以跳过):

  • 命令处理程序更新聚合A的状态可以从存储库中获取聚合B,对其调用计算并将结果放入域事件中;然而,我相信,除了一个被修改的聚合之外,获取聚合不是命令处理程序的工作,即使是为了读取目的;另外,命令处理程序的任务不是执行计算,只是发送事件,而不是修改域的状态
  • 由聚合A引发的域事件(“聚合A已更新”)仅包含聚合A的更新状态,有关聚合B状态的信息不足。读取模型的事件处理程序无法访问域模型,因此它既无法获取聚合B,也无法调用聚合B上所需的函数来更新读取模型
  • 我知道命令所需的任何状态,如果是在被修改的聚合之外,都必须随命令一起传递。这样,应用程序服务在发送命令之前可以获取聚合B的状态(从读取模型),并将其放入命令中。为此,我必须将函数从聚合B移动到某个服务,并在那里传递A和B的状态。这将使聚合B更贫血。加上上面提到的在命令处理程序中进行计算的问题
  • 我曾读到有人建议,任何只有read模型感兴趣的计算都属于read模型本身。因此,我的事件的read模型的处理程序可以处理执行计算所需的所有状态和行为。然而,这意味着我必须在查询端复制许多领域模型概念;拥有一个完整的读取模型太复杂了
我刚刚想到了以下解决方案:在域中,创建一个域事件“聚合一个更新的”的处理程序。它将获取聚合B,调用其上的计算方法,然后引发“聚合B函数结果已更改”事件,其中包含新的计算结果。然后读取模型能够从该事件中获取结果并更新自身。这样行吗

请注意,以防我没有使用事件源

如果您对这种情况有任何想法,我们将不胜感激。谢谢

更新:使情况更加具体

我的聚合是
Worker
s(聚合B)和
Group
s(聚合B)。工人和团体是一种多对多的关系。假设一个组和一个工作者都有一些
属性。工人的
calculateValue()
是工人的值加上工人参与的所有组的值的函数。上面描述的命令正在修改某些组的
。因此,参与组的所有工作人员都将返回不同的
calculateValue()
结果

我想从read模型中得到什么?我想要一个具有计算值的工作人员列表(已经考虑了工作人员的所有组中的值)。我甚至不需要在阅读端建立团队。如果我采用“在阅读端进行计算”的方式,我需要团队以及关系的整体结构。恐怕这会是一个不合理的复杂情况

命令处理程序更新聚合A的状态可以从存储库中获取聚合B,对其调用计算并将结果放入域事件中;然而,我相信,除了一个被修改的聚合之外,获取聚合不是命令处理程序的工作,即使是为了读取目的;另外,命令处理程序的任务不是执行计算,只是发送事件,而不是修改域的状态

这是不正确的,因为事件应该表示与单个聚合相关的事实

我知道命令所需的任何状态,如果是在被修改的聚合之外,都必须随命令一起传递。这样,应用程序服务在发送命令之前可以获取聚合B的状态(从读取模型),并将其放入命令中。为此,我必须将函数从聚合B移动到某个服务,并在那里传递A和B的状态。这将使聚合B更贫血。加上上面提到的在命令处理程序中进行计算的问题

不应在事件中发送聚合状态。事实上,您不应该查询聚合,也不应该以任何其他方式使用它的内部和私有状态,而应该由聚合本身使用在CQRS中,不查询聚合。这就是阅读模型的目的

我曾读到有人建议,任何只有read模型感兴趣的计算都属于read模型本身。因此,我的事件的read模型的处理程序可以处理执行计算所需的所有状态和行为。然而,这意味着我必须在查询端复制许多领域模型概念;拥有一个完整的读取模型太复杂了

这就是路。然而,你到底复制了什么?聚合是否使用该计算的结果来接受或拒绝其任何命令

如果是,则应在命令执行时在聚合内执行,并可能在事件中发送最终结果,但前提是计算可以使用来自命令和/或内部聚合状态的数据,而不是交叉聚合