Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/31.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Architecture 域事件处理程序-它们是否应用于应用层问题?_Architecture_Domain Driven Design_Domain Events - Fatal编程技术网

Architecture 域事件处理程序-它们是否应用于应用层问题?

Architecture 域事件处理程序-它们是否应用于应用层问题?,architecture,domain-driven-design,domain-events,Architecture,Domain Driven Design,Domain Events,在实现域事件时,事件处理程序应仅用于纯域关注点;您将与业务专家讨论的内容,或者他们是否愿意被任何对域模型感兴趣的人使用 这可能最简单地用一个简单的例子来解释,考虑一个日历应用程序来安排员工的工作。 我们可能有以下域事件 任命增加 免职 任命内容已更改 委任动议 我们有这些事件的处理程序,例如,当约会移动到员工工作时间以外的时间时,我们会设置一个警告标志 当然,应用程序关注的是这些事件,例如,当约会添加到日历中时,我们应该将其添加到工作单元中,以便稍后提交更改 这些应用程序关注点应该是域事件的消费

在实现域事件时,事件处理程序应仅用于纯域关注点;您将与业务专家讨论的内容,或者他们是否愿意被任何对域模型感兴趣的人使用

这可能最简单地用一个简单的例子来解释,考虑一个日历应用程序来安排员工的工作。

我们可能有以下域事件

任命增加 免职 任命内容已更改 委任动议

我们有这些事件的处理程序,例如,当约会移动到员工工作时间以外的时间时,我们会设置一个警告标志

当然,应用程序关注的是这些事件,例如,当约会添加到日历中时,我们应该将其添加到工作单元中,以便稍后提交更改


这些应用程序关注点应该是域事件的消费者,还是我们应该提出并处理单独的系统事件呢?

如果您指的是交叉关注点,那么如果您的应用程序逻辑需要,您将被迫使用它。因此,它将与其他事件处理代码混合

但是,如果您需要在域事件发生时做一些独立的事情,那么最好使用单独的事件处理程序(请参阅关注点分离原则)


顺便说一下,在第一种情况下,尽量避免将域逻辑与事件处理(基础设施)逻辑混合。左基础结构/横切关注调用域方法的事件处理程序中的代码。在域对象的方法中移动域代码。

在DDD解决方案中使用事件有两种行之有效的方法

第一个是基于Udi Dahan的。如果你还没有读过,我强烈建议你。总之,除了正常的ORM样式行为之外,还可以使用静态类发布事件。因此,您将订单添加到客户的订单集合,并发布该事件。因为域行为是在事务范围内执行的,所以事件处理程序也是。您还可以在那里找到不要将对象手动附加到工作单元的建议。应通过调用现有根上的行为来创建新的聚合根


还有另一个选择是由格雷格·杨提出的。它基于事件源,基本上是使用事件作为保持状态的手段。在这种方法中,聚合根通常使用一些基础结构(例如基本聚合根类)来应用事件。Apply确实调用聚合根类上的事件处理程序,并在总线上发布此事件(无论您使用什么总线实现)。

这听起来很合理,但它导致了一个关于何时引发域事件的新问题。假设将约会添加到日历是在事务中执行的,将实体添加到UnitOfWork必须在事务中执行,但更新UI必须在事务之外执行。在这种情况下,是否应在事务中引发域事件?UI更新应该在另一个异步工作的域事件处理程序中完成。域事件表示已经发生的事情。因此,在事件处理程序中应该没有回滚事务的能力。Commit transaction然后为事务期间发送的所有事件调用事件处理程序。我怀疑它们在触发该事件的聚合的同一事务中提升事件处理。正如我所记得的,Udi指定最好在聚合事务之外“触发并忘记”,特别是在事件处理程序与域无关的情况下(例如电子邮件消息)。“触发并忘记”意味着你不在乎听者是否收到消息,但你应该关心何时触发消息(发送消息)。在聚合完成其作业后发送一条消息:状态更改+持久性。所以我建议在坚持之后触发一个事件。聚合可以随时触发事件,但实际的消息传递应该在聚合持久化之后(或触发事件的特定命令完成之后)进行处理。