Nor*_*ard 5 domain-driven-design domain-events
在 DDD 文献中,返回域事件模式被描述为管理域事件的一种方式。从概念上讲,聚合根保留了一个域事件列表,当您对其进行某些操作时会填充该列表。
当对聚合根的操作完成后,DB 事务在应用服务层完成,然后应用服务对域事件进行迭代,调用事件调度器来处理这些消息。
我的问题是关于我们现在应该如何处理交易。Event Dispatcher 是否应该负责为它处理的每个事件管理一个新事务?或者应用程序服务应该在它调用域事件调度器的域事件迭代中管理事务?当调度程序使用像 RabbitMQ 这样的基础设施机制时,问题是无关紧要的,但是当域事件在进程中处理时,问题就无关紧要了。
与我的问题相关的子问题。您对使用 ORM 钩子(即:NHibernate 的 IPostInsertEventListener、IPostDeleteEventListener、IPostUpdateEventListener)在聚合根上启动域事件迭代而不是在应用程序服务中手动执行此操作有何看法?它是否增加了太多的耦合?是否更好,因为它不需要在每个用例中编写相同的代码(域事件在聚合上循环,如果它不在调度程序内部,则可能创建新事务)?
我的问题是关于我们现在应该如何处理交易的方式。事件调度程序是否应该负责管理它处理的每个事件的新事务?或者应用程序服务是否应该在调用域事件调度程序的域事件迭代内管理事务?
您在这里问的实际上是这个问题的一个专门版本:我们是否应该在单个事务中更新多个聚合?
你会发现很多断言的答案都是“不”。例如,沃恩·弗农 (2014)
正确设计的聚合是可以按照业务所需的任何方式进行修改的聚合,并且其不变量在单个事务中完全一致。在所有情况下,正确设计的有界上下文只会修改每个事务的一个聚合实例。
Greg Young 倾向于走得更远,指出遵守此规则允许您通过聚合 ID 来分区数据。换句话说,聚合边界是如何组织数据的明确表达。
因此,最好的选择是尝试安排更复杂的编排,以便每个聚合都在自己的事务中更新。
我的问题与我们处理初始交易完成后更改初始聚合后发送的事件的交易方式有关。必须处理领域事件,并且其过程可能需要更改另一个聚合。
是的,所以如果我们要更改另一个聚合,那么应该(根据上面的建议)有一个新的事务来更改聚合。换句话说,不是域事件的路由决定了我们是否需要另一个事务——事件处理程序的选择决定了我们是否需要另一个事务。