You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

六边形架构中application包应放什么?ArchUnit测试疑问

六边形架构中Application包的职责与内容规划

问题背景

我正在实现遵循DDD原则的简易六边形架构:

  • domain包存放领域模型(Domain Models)和领域服务(Domain Services)
  • adapter包包含入站、出站适配器
  • 最初将ports放在application包,配置ArchUnit的ApplicationService路径后,出现domain包访问application包的依赖问题:
    Class <...domain.services...> implements interface <...application.ports.in...>
    
  • 将ports移到domain包后解决了依赖问题,但疑惑application包及ApplicationService的用途,不知道该包应放置什么内容。

当前架构结构:

- adapter
  |- inbound
  |- outbound
- domain
  |- model
  |- services
  |- ports
- application
  |- ???
- Application.kt

当前ArchUnit测试代码:

val `hexagonal architecture is respected`: ArchRule = onionArchitecture()
    .domainModels("$rootPackage.domain.model..")
    .domainServices("$rootPackage.domain.services..", "$rootPackage.domain.ports..")
    .applicationServices("$rootPackage.application..")
    .adapter("Adapter", "$rootPackage.adapter..")
    .withOptionalLayers(true)

核心解答:Application包的职责与内容

application包是领域层与外部适配器之间的协调层,不包含核心业务逻辑,主要负责流程编排、外部请求适配、全局事务/异常处理等,具体可放置以下内容:

1. 应用服务(Application Services)

这是application包的核心,作为入站适配器(如API控制器、消息消费者)和领域层的中间层,做以下事情:

  • 接收外部请求,转化为领域层能处理的调用(比如把DTO转成领域实体)
  • 编排多个领域服务的调用流程(比如创建订单时,先调用库存领域服务扣减库存,再调用订单领域服务创建订单)
  • 管理事务边界(比如用@Transactional注解包裹整个业务流程)
  • 调用出站适配器的实现(通过领域层的ports)
  • 将领域层的结果转化为外部需要的响应格式(比如把领域实体转成DTO)

举个例子:OrderApplicationService的createOrder方法,会接收CreateOrderRequest,调用InventoryDomainService.checkAndDeductStock,再调用OrderDomainService.createOrder,最后调用OrderRepositoryPort.save完成持久化。

2. 请求/响应DTO

定义外部系统与应用层交互的数据结构:

  • 入站DTO:比如API控制器接收的CreateOrderRequest,隔离外部请求格式与领域模型
  • 出站DTO:比如返回给前端的OrderResponse,避免领域模型的内部结构暴露给外部

3. 全局异常处理

统一处理领域层抛出的业务异常,转化为外部适配器能识别的错误格式:

  • 比如把领域层的StockInsufficientException转化为HTTP 400响应
  • 集中处理异常,避免在每个适配器中重复编写异常处理逻辑

4. 全局配置(可选)

如果有跨适配器或跨领域的全局配置,可放在这里(比如全局的事务配置、消息队列配置),不过这类配置也可以放在启动类所在的根包下,根据项目习惯调整。

5. 应用层端口(可选)

如果需要定义更上层的调用契约(比如某些复杂的跨领域操作入口),可以在这里定义应用层的端口,但通常入站适配器直接调用应用服务即可,不需要额外定义端口。

调整后的架构示例

- adapter
  |- inbound
     |- rest (API控制器,调用应用服务)
     |- messaging (消息消费者,调用应用服务)
  |- outbound
     |- persistence (实现领域层的仓储端口)
     |- notification (实现领域层的通知端口)
- domain
  |- model (领域实体、值对象,核心业务逻辑)
  |- services (领域服务,处理跨实体的业务逻辑)
  |- ports
     |- in (领域层对外暴露的操作入口,如`CreateOrderUseCase`)
     |- out (领域层依赖的外部资源抽象,如`OrderRepositoryPort`)
- application
  |- services (应用服务,如`OrderApplicationService`)
  |- dto (请求/响应对象,如`CreateOrderRequest`、`OrderResponse`)
  |- exception (全局异常处理类,如`ApplicationExceptionHandler`)
- Application.kt (项目启动类)

ArchUnit配置说明

当前的ArchUnit配置是正确的:

  • domainServices包含domain.ports..,因为ports是领域层的一部分(依赖倒置原则,领域定义自身的依赖抽象)
  • applicationServices指向application..,应用服务属于应用层,依赖领域层,不会出现反向依赖问题

内容的提问来源于stack exchange,提问作者Danny Steinbrecher

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 10:12:27