domain-driven-design - 领域驱动设计 (DDD) : Domain Event Handlers – Where to place them?

标签 domain-driven-design business-logic domain-events hexagonal-architecture

我对在基于六边形架构的应用程序中处理域事件的位置感到困惑。我说的是有界上下文内部域事件,而不是上下文间集成/应用程序/公共(public)事件。
背景
据我所知,应用程序逻辑(即用例逻辑、工作流逻辑、与基础设施的交互等)是命令处理程序所属的地方,因为它们特定于某个应用程序设计和/或 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.
    }
    

    最佳答案

    大多数偶数处理程序类的问题在于它们通常与特定的消息传递技术相关,因此通常放置在 infrastructure layer 中。 .
    但是,没有什么可以阻止您编写与技术无关的处理程序并使用向它们调度的技术感知适配器。
    例如,在我构建的一个应用程序中,我有一个 的概念。需要采取行动的政策 .该策略驱动了给定 的分配/取消分配工作项目 每当满足/不满足策略规则时,都会分配到一个特殊的工作负载桶。在许多情况下必须重新评估该政策,例如当文档附加到 时。工作项目 ,当工作项目 已分配,何时授予外部状态标志等。
    我最终创建了一个 ActionRequiredPolicy域中具有事件处理方法的类,例如 void when(CaseAssigned event)我在基础设施层有一个偶数处理程序,它只是通知策略。
    我认为人们将这些放在 infrastructure 中的另一个原因或 application层是策略通常通过触发新命令对事件使用react。有时这种方法感觉很自然,但有时您想明确表示一个 Action 必须响应事件而发生,否则不会发生:将事件转换为命令使其不那么明确。
    这是一个 older question我问了相关的。

    关于domain-driven-design - 领域驱动设计 (DDD) : Domain Event Handlers – Where to place them?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67148194/

    相关文章:

    domain-driven-design - 将遗留数据库迁移到 cqrs/事件源 View

    database - 从数据层填充域模型,还是直接查询数据库?

    java - 具有可选参数和不同业务逻辑的Web服务

    c# - 在 C# 中对域事件进行排队

    c# - 在 DDD 的哪一层将类声明为聚合根?

    node.js - 我应该转向基于微服务的架构吗?

    java - 如何设计业务流程层

    php - 如何在 PHP 中为目标建模和跟踪需求

    domain-driven-design - ApplicationEvent 与 DomainEvent 有何不同?

    event-handling - 没有 CQRS 的领域事件和版本控制