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

And*_*cus 7 architecture domain-driven-design domain-events

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

最好用一个简单的例子来解释这个问题,考虑一个Calendar应用程序来为员工安排工作.

我们可能会有以下域名事件......

AppointmentAdded AppointmentRemoved AppointmentContentChanged AppointmentMoved

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

当然存在对这些事件感兴趣的应用程序问题,例如,当将约会添加到日历时,我们应该将其添加到工作单元,以便我们可以稍后提交更改.

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

Szy*_*ega 5

在DDD解决方案中有两种完善的事件使用方法.

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

Greg Young还推出了另一种选择.它基于事件采购,基本上使用事件作为持久状态的手段.在这种方法中,您的聚合根通常使用一些基础结构(例如基本聚合根类)来应用事件.Apply会在聚合根类上调用事件处理程序,在总线上发布此事件(无论您使用何种总线实现).

  • 我怀疑它们在与触发该事件的聚合相同的事务中促进事件处理.正如我记得的那样,Udi指出最好"发射并忘记"现场聚合事务,特别是在事件处理程序与域无关的情况下(例如:电子邮件消息)."发射并忘记"意味着您不关心侦听器是否收到消息,但您应该关心何时触发消息(发送消息).您在聚合完成它的工作后发送消息:状态更改+持久性.因此,我坚持不懈地发起一场事件. (3认同)
  • PS任何时候聚合都可以触发事件,但实际的消息传递应该在聚合持久性之后(或者在触发事件的特定命令完成之后)处理. (2认同)