洋葱架构的 DDD 端口和适配器,什么去哪里?

DDD Ports and Adapters with Onion architecture, what goes where?

想弄明白一些概念一直没能看懂

端口和适配器架构中的用例是什么?

用例的实现是什么样的?

什么是用例问题?

它在基础设施或域中的什么位置,它说它在应用程序中,那么根据我的理解,应用程序核心和应用程序服务是不同的?

On the left side, the adapter depends on the port and gets injected a concrete implementation of the port, which contains the use case. On this side, both the port and its concrete implementation (the use case) belong inside the application;

https://herbertograca.com/2017/09/14/ports-adapters-architecture/#what-is-a-port

这句话让我感到困惑……因为据我所知,主适配器可以是任何要求您的业务逻辑的东西(它对您提供的内容感兴趣)WebAPI、MVC、测试、ConsoleApp。

On the left side, the adapter depends on the port and gets injected a concrete implementation of the port which contains the use case.

所以我假设它指的是您的业务逻辑被注入让我们说一个 WebApiController 构造函数

On this side, both the port and its concrete implementation (the use case) belong inside the application;

那又怎样?这是谁

application

是 WebApi 吗?还是域?我理解的用例也是我的业务逻辑的实现,所以例如设计会是这样的?

Client :
WebApiController(IMyBusinessServicePort service)

Infrastructure :
ImplementingPrimaryAdapter : IMyBusinessServicePort { }
ImplementingSecondaryAdapter : ILoggingPort { }

Domain :
ImplementMyBusinessLogicService : IMyBusinessLogicService 

所以 WebApiController 将使用 ImplementingPrimaryAdapter 提供的实现,而不是来自我的域的东西?我不明白

请解释。

六边形建筑并没有说明六边形的内部结构。

用例如下:

驱动程序端口是应用程序的用例边界(六边形)。用例接口将是驱动程序端口。用例的实现将是六边形内的 class。

Alistair所说的应用不是DDD应用层,是业务逻辑整体,六边形,与技术解耦。如果你想与 DDD 层进行比较,六边形必须分为两层:应用程序和域。 ddd 基础设施层将是六边形之外的适配器。

但是六边形架构并没有说明 DDD,它们是不同的东西。如何让 DDD 适合六边形架构,由您决定。

我写过一篇关于六边形建筑的文章,如果你想修正概念:

https://jmgarridopaz.github.io/content/hexagonalarchitecture.html

希望对您有所帮助。

根据您使用的是基于调用堆栈的编程还是 Actor 模型等,实现方式存在一些差异。

接下来我讲一个最接近DDD和CQRS中"C"部分的案例:改变系统的状态。 "Q" 从 Hexagon 方面看,部分更简单:它的复杂性主要在适配器方面。

我呢,我把词汇放在六边形的核心。它映射到 DDD 无处不在的语言模型,由不可变的数据结构组成,并在这些数据结构上验证业务不变量。

接下来是决策环节。当你做出决定时,根据单一职责原则,你应该只做这个。不进行外部调用、IO 等。因此,您需要一些信息来做出决定。收集此信息后,可以将 in 包装在 Command 对象中。您将其传递给决策者,后者大致映射到 DDD 聚合。然后它要么批准命令并生成事件或变更集(无论您是否执行 EventSourcing),要么拒绝。无需任何外部调用。 IE。它不使用任何 Hexagon 的端口。

Hexagon 内部剩下的是收集外部数据、调用决策者和处理结果的逻辑。该逻辑可以建模为简单的有限状态机并进行单元测试。这就是我在 Hexagon 中所说的用例。因为这是协调港口和决策者之间数据流动的地方。因此,一个用例使用端口。

在 Hexagon 的主要端口上收到业务请求后,将创建一个用例实例。有一个UseCase的FSM和executor,实际调用secondary ports,接收他们的响应并推进用例FSM。

一个用例的处理流程可以包括以下步骤:

  • 验证收到的业务请求
  • 如果无效 - 格式错误的业务响应
  • 如果有效 - 准备对辅助端口的请求
  • 发送准备好的请求
  • 接收辅助端口的响应
  • 如果出现故障或超时 - 格式错误的业务响应
  • 如果数据收集成功,为决策者准备命令
  • 打电话给决策者然后回来Event/Changeset/Rejection
  • 如果被拒绝 - 格式错误的业务请求
  • 如果被接受 - 为辅助端口准备另一组请求以执行决策:持久化到 DB、发送到 MQ、发射火箭等。
  • 等待辅助端口执行请求
  • 如果失败 - 格式错误的业务响应
  • 如果正常 - 成功格式化业务响应

因此,一个用例肯定属于一个域,因为它不依赖于适配器的实现,而是依赖于它们的接口。并且构成了Domain的应用层。

将用例放在单独的代码片段中很有用,因为这样代码更改的原因只有一个——如果用例发生更改。它不同于决策制定逻辑或域值验证逻辑。

域名:

  1. 端口(连接域与基础设施)
  2. 应用服务
  3. 域服务
  4. 域工厂
  5. 域实体

基本上,您不会将任何基础架构问题泄露到您的域中,而是使用抽象。

基础架构层,任何可以更改的内容,ORM、缓存、日志记录等等...