我对在基于六边形架构的应用程序中处理域事件的位置感到困惑。我说的是有界上下文内部域事件,而不是上下文集成/应用程序/公共事件。
背景
据我了解,应用程序逻辑(即用例逻辑、工作流逻辑、与基础设施的交互等)是命令处理程序所属的地方,因为它们特定于某个应用程序设计和/或 UI 设计。然后,命令处理程序调用所有域逻辑所在的域层(域服务、聚合、域事件)。领域层应该独立于特定的应用程序工作流和/或 UI 设计。
在许多资源(博客、书籍)中,我发现人们在应用层实现域事件处理程序,类似于命令处理程序。这是因为域事件的处理应该在它自己的事务中完成。由于它可能会影响其他聚合,因此必须首先通过基础架构加载这些聚合。然而,关键点是:领域事件被撕裂并变成一系列对聚合的方法调用。这个重要的翻译只存在于应用层。
问题
我认为关于哪些领域事件会对其他聚合产生什么影响的知识是领域知识本身的一个组成部分。如果我要删除除我的领域层之外的所有内容,那么这些知识不应该保留在某个地方吗?在我看来,我们应该将领域事件处理程序直接放在领域层本身:
它们可以是接收域事件和可能受其影响的聚合的域服务,并将域事件转换为一个或多个方法调用。
它们可以是聚合本身的方法,直接使用整个域事件(即签名包含域事件类型)并使用它做任何他们想做的事情。
当然,为了加载受影响的聚合,我们仍然需要在应用层有一个对应的处理程序。这个处理程序只启动一个新事务,加载感兴趣的聚合并调用到域层。
由于我从未在任何地方看到过这个,我想知道我是否对 DDD、域事件或应用层和域层之间的区别有什么问题。
编辑:示例
让我们从这个常用的方法开始:
// in application layer service (called by adapter)
public void HandleDomainEvent(OrderCreatedDomainEvent event) {
var restaurant = this.restaurantRepository.getByOrderKind(event.kind);
restaurant.prepareMeal(); // Translate the event into a (very different) command - I consider this important business knowledge that now is only in the application layer.
this.mailService.notifyStakeholders();
}
而这个呢?
// in application layer service (called by adapter)
public void HandleDomainEvent(OrderCreatedDomainEvent event) {
var restaurant = this.restaurantRepository.getByOrderKind(event.kind);
this.restaurantDomainService.HandleDomainEvent(event, restaurant);
this.mailService.notifyStakeholders();
}
// in domain layer handler (called by above)
public void HandleDomainEvent(OrderCreatedDomainEvent event, Restaurant restaurant) {
restaurant.prepareMeal(); // Now this translation knowledge (call it policy) is preserved in only the domain layer.
}