洋葱架构的 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的应用层。
将用例放在单独的代码片段中很有用,因为这样代码更改的原因只有一个——如果用例发生更改。它不同于决策制定逻辑或域值验证逻辑。
域名:
- 端口(连接域与基础设施)
- 应用服务
- 域服务
- 域工厂
- 域实体
基本上,您不会将任何基础架构问题泄露到您的域中,而是使用抽象。
基础架构层,任何可以更改的内容,ORM、缓存、日志记录等等...
想弄明白一些概念一直没能看懂
端口和适配器架构中的用例是什么?
用例的实现是什么样的?
什么是用例问题?
它在基础设施或域中的什么位置,它说它在应用程序中,那么根据我的理解,应用程序核心和应用程序服务是不同的?
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的应用层。
将用例放在单独的代码片段中很有用,因为这样代码更改的原因只有一个——如果用例发生更改。它不同于决策制定逻辑或域值验证逻辑。
域名:
- 端口(连接域与基础设施)
- 应用服务
- 域服务
- 域工厂
- 域实体
基本上,您不会将任何基础架构问题泄露到您的域中,而是使用抽象。
基础架构层,任何可以更改的内容,ORM、缓存、日志记录等等...