具有洋葱架构的DDD端口和适配器,去哪儿去了?

时间:2018-09-13 21:22:01

标签: design-patterns architecture domain-driven-design software-design hexagonal-architecture

试图弄清楚一些概念并且还无法理解

Ports and Adapters体系结构中的用例是什么?

用例的实现是什么样子?

什么是用例关注点?

它在基础结构或域中适合的位置是什么,它说它可以在应用程序中使用,以及据我所知,有哪些应用程序核心和应用程序服务不同?

  

在左侧,适配器取决于端口并被注入   端口的具体实现,其中包含用例。上   在这方面,港口及其具体实施(使用   案例)属于应用程序内部;

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

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

  

在左侧,适配器取决于端口并被注入   包含用例的端口的具体实现。

所以我假设它是指您的业务逻辑被注入let中,例如说一个WebApiController构造函数

  

在这一方面,端口及其具体实现(使用   案例)属于应用程序内部;

那又怎样?这是谁

  

应用

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

Client :
WebApiController(IMyBusinessServicePort service)

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

Domain :
ImplementMyBusinessLogicService : IMyBusinessLogicService 

因此,WebApiController将使用ImplementingPrimaryAdapter提供的实现,而不是我的域提供的东西?我不明白

请解释。

3 个答案:

答案 0 :(得分:2)

六角形结构没有说明六角形的内部结构。

用例如下:

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

Alistair所谓的应用程序不是ddd应用程序层,而是与技术分离的整体业务逻辑,六边形。如果要与ddd层进行比较,则必须将六边形分为两层:应用程序层和域。 ddd基础结构层将是六边形之外的适配器。

但是六角形体系结构没有说明DDD,它们是不同的东西。如何将DDD与六边形结构配合使用由您决定。

如果您要修复概念,我已经写了一篇有关六角形体系结构的文章:

https://softwarecampament.wordpress.com/portsadapters

希望有帮助。

答案 1 :(得分:2)

在实现上有一些差异,具体取决于您是使用基于调用堆栈的编程还是例如Actor模型。

接下来,我将讨论一个最接近CQRS中DDD和“ C”部分的情况:对系统状态进行更改。从Hexagon方面来看,“ Q”部分更简单:它的复杂性主要在适配器方面。

对于我来说,我将词汇放在六边形的核心中。它映射到DDD通用语言模型,由不可变数据结构组成,并验证了这些数据结构上的业务不变量。

接下来,有一个决策点。在做出决定时,根据“单一责任原则”,您仅应这样做。不进行外部呼叫,IO等。因此,您需要一些信息才能做出决定。收集此信息后,可以将它们包装在Command对象中。您将其传递给决策者,后者大致映射到DDD聚合。然后,它批准命令并生成事件或变更集(无论是否执行EventSourcing)或拒绝。没有任何外部呼叫。即它不使用任何Hexagon的端口。

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

在Hexagon的主端口上收到业务请求后,将创建一个用例实例。有一个UseCase的FSM和执行程序,他们实际上调用辅助端口,接收其响应并推进用例FSM。

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

  • 验证收到的业务请求
  • 如果无效-格式化带有错误的业务回复
  • 如果有效-准备对辅助端口的请求
  • 发送准备好的请求
  • 接收辅助端口的响应
  • 如果发生故障或超时,请格式化带有错误的业务响应
  • 如果数据收集成功,请为Command的决策者准备Command
  • 致电决策者并获取事件/变更集/拒绝
  • 如果被拒绝-格式化带有错误的业务请求
  • 如果被接受,则为辅助端口准备另一组请求以执行决定:坚持到数据库,发送到MQ,发射火箭等。
  • 等待次端口执行请求
  • 如果失败-格式化带有错误的业务回复
  • 如果可以,请设置成功的业务回复格式

因此,用例绝对属于域,因为它不依赖于适配器的实现,而是依赖于它们的接口。并构成域的应用程序层。

将用例放在单独的代码片段中很有用,因为通过这种方式,此代码将只有一个更改的理由-如果用例发生了更改。它不同于决策逻辑或域值验证逻辑。

答案 2 :(得分:1)

域:

  1. 端口(将域与基础架构连接起来)
  2. 应用服务
  3. 域服务
  4. 域工厂
  5. 域实体

基本上,您不会在您的域中发现任何基础设施方面的问题,而是使用抽象。

基础结构层,任何可能发生更改,ORM,缓存,日志记录等的事物……