【发布时间】:2018-03-27 00:59:34
【问题描述】:
我是 DDD 的新手,我正在我的应用程序的一部分上实现它,因为应用程序的一些要求引导我使用事件源的 CQRS(需要系统中发生的事件的历史记录加上需要能够查看系统过去的状态)。
阅读 Vaughn Vernon 的书及其有效的聚合设计系列后,我有一个问题是流程管理器(长期运行的进程)和域服务之间的区别是什么。特别是当您将导航属性指向另一个聚合时
我会解释我所理解的:
- 域服务用于保存不属于任何聚合的逻辑。根据 Vaughn 的说法,它也可以用于将实体引用传递给包含它的聚合。它也可以用来管理事务,因为它们不能被处理到域对象中
- 流程管理器用于协调对系统进行的修改并跨越不同的聚合。有人说一个好的流程管理器实际上是一个聚合根。据我了解,它不管理事务,因为在提交更改后启动事件。它使用最终一致性的方法。最终所有的变化都会发生
现在,将所有内容放在上下文中。我正在构建的应用程序的核心是处理包含它们自己的逻辑的节点树。我们需要能够将节点添加到树中,当然还需要创建这些节点。
我们需要能够知道这些节点发生了什么。即我们需要能够检索链接到节点的事件
此外,对其中一个叶子所做的修改(取决于修改的类型)将必须复制到作为该节点的父节点的其他节点。
什么是我的聚合:
- 节点,这是我的树包含的内容。在我看来,这是一个汇总有几个原因。它不是不变量,因此不是值对象。他们有自己的领域逻辑,允许他们分配它的属性它的值对象,我们需要能够使用 Ids 访问它们
- 由节点组成的非二叉树的表示。现在,我实际上将它设计为我的聚合根,它实际上是一个流程管理器。该树包含该树的逻辑表示。它包含树的根。这个根实际上是一个对象(我不确定它是否可以命名为值对象,因为它包含对其他聚合子节点的引用,但听起来确实如此)。树中的节点对象包含节点名称等基本信息,以及对实际聚合的引用(这几乎听起来像两个有界上下文?)
使用这种方法正在发生这种情况:
- 执行创建节点的命令后,节点被创建并提交。启动 NodeCreated 事件,被正确的处理程序捕获,该处理程序检索与此节点关联的树(进程管理器)并将节点添加到正确的位置(使用节点的父 id 属性)
- 执行命令修改节点后,节点被修改并提交。 NodeModified 事件被启动,被处理程序捕获。然后,处理程序检索树(我的流程管理器)并找到修改节点的所有父节点,并要求这些节点根据子节点上的修改来修改自己的属性。这一切都很有道理,在我看来几乎是美丽的,展示了事件的力量和领域逻辑的分离
但是,我的主要问题是交易。如果在更新树和必须修改或添加的节点时发生错误,会发生什么?节点的事件已保存在事件存储中,因为它已提交。所以我必须创建一个新事件来恢复修改?我知道命令在进入系统时必须是有效的,所以它不会是一个验证问题,并且发生某些事情的可能性是百万分之一。这是否意味着我们不应该考虑这种可能性?
交易问题是我觉得我应该使用服务的原因。一个应用程序服务(这里是一个命令处理程序)或一个域服务来编排动作并在单个事务中执行它们。如果在此事务中发生故障,则不会创建/修改任何内容,但这违反了 DDD 的规则,即我不应该在同一个事务中修改多个聚合。这在某种程度上看起来是一个不太优雅的解决方案
我真的觉得我在这里遗漏了一些东西,但我不太确定它是什么。
【问题讨论】: