5

在 DDD 文献中,返回域事件模式被描述为管理域事件的一种方式。从概念上讲,聚合根保留了一个域事件列表,当您对其执行某些操作时会填充该列表。

当聚合根上的操作完成时,数据库事务在应用服务层完成,然后应用服务迭代域事件,调用事件调度器来处理这些消息。

我的问题是关于我们现在应该如何处理交易。Event Dispatcher 是否应该负责为其处理的每个事件管理新事务?或者应用程序服务是否应该在它调用域事件调度程序的域事件迭代中管理事务?当调度程序使用像 RabbitMQ 这样的基础结构机制时,这个问题是无关紧要的,但是当域事件在进程内处理时,它就是。

与我的问题相关的子问题。您对使用 ORM 挂钩(即:NHibernate 的 IPostInsertEventListener、IPostDeleteEventListener、IPostUpdateEventListener)在聚合根上而不是在应用程序服务中手动执行域事件迭代有什么看法?它是否增加了太多的耦合?是否更好,因为它不需要在每个用例中编写相同的代码(域事件在聚合上循环,如果它不在调度程序内部,则可能创建新事务)?

4

2 回答 2

3

我的问题是关于我们现在应该如何处理交易。Event Dispatcher 是否应该负责为其处理的每个事件管理新事务?或者应用程序服务是否应该在它调用域事件调度程序的域事件迭代中管理事务?

您在这里问的是这个问题的一个特殊版本:我们是否应该在单个事务中更新多个聚合?

你可以找到很多断言答案是否定的。例如,沃恩弗农 (2014)

正确设计的聚合是可以以业务所需的任何方式修改的聚合,其不变量在单个事务中完全一致。在所有情况下,正确设计的有界上下文仅修改每个事务的一个聚合实例。

Greg Young 倾向于走得更远,他指出遵守此规则允许您按聚合 id 对数据进行分区。换句话说,聚合边界是如何组织数据的明确表达。

因此,最好的办法是尝试安排更复杂的编排,以便每个聚合都在其自己的事务中更新。

我的问题与我们在初始事务完成后更改初始聚合后发送的事件的事务处理方式有关。必须处理域事件,并且其过程可能需要更改另一个聚合。

是的,所以如果我们要更改另一个聚合,那么(根据上面的建议)应该有一个新的事务来更改聚合。换句话说,不是域事件的路由决定了我们是否需要另一个事务——事件处理程序的选择决定了我们是否需要另一个事务。

于 2017-11-12T13:51:29.387 回答
2

仅仅因为事件处理发生在进程中并不意味着原始应用程序服务必须协调所有由于事件而发生的事务。

例如,如果我们通过 Observable 模式进行进程内事件处理,每个 Observer 将负责在需要时创建自己的事务。

您对使用 ORM 挂钩(即:IPostInsertEventListener、IPostDeleteEventListener、NHibernate 的 IPostUpdateEventListener)在聚合根上而不是在应用程序服务中手动执行域事件迭代有什么看法?

这不是必须在原始数据库事务期间发生,有效地将所有内容转变为即时一致性(如果事件在进程中处理)?

于 2017-11-14T10:33:35.660 回答