【问题标题】:DDD Ports and Adapters with Onion architecture, what goes where?洋葱架构的 DDD 端口和适配器,哪里去了?
【发布时间】:2018-09-13 21:22:01
【问题描述】:

想弄清楚一些概念却一直没能理解

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

用例的实现是什么样的?

什么是用例关注点?

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

在左侧,适配器依赖于端口并被注入一个 端口的具体实现,其中包含用例。在 这边,无论是端口还是它的具体实现(使用 case) 属于应用程序内部;

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

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

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

所以我假设它指的是你的业务逻辑被注入 let;s 说一个 WebApiController 构造函数

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

那又怎样?这是谁

应用

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

Client :
WebApiController(IMyBusinessServicePort service)

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

Domain :
ImplementMyBusinessLogicService : IMyBusinessLogicService 

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

请解释一下。

【问题讨论】:

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


    【解决方案1】:

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

    用例适合这样:

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

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

    但是六边形架构并没有说明 DDD,它们是不同的东西。如何将 DDD 与六边形架构配合使用取决于您。

    我写了一篇关于六边形架构的文章,如果你想修正这些概念:

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

    希望对你有帮助。

    【讨论】:

    • 请提一个问题,所以如果驱动端口代表第 3 方包、库、框架的抽象...和驱动适配器只是这些端口的实现。驱动端口如何表示?谁来实现它?这是 mediatR 适合的地方吗?只是为了尽快将音乐会扔给应用程序?所以 MediatR 是实际的驱动适配器,假设 WebApi 是驱动端口?
    • 驱动端口由六边形内部实现。如果实现需要来自外部世界的某些东西,它会调用驱动端口。我在文章里解释过
    【解决方案2】:

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

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

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

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

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

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

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

    • 验证收到的业务请求
    • 如果无效 - 格式错误的业务响应
    • 如果有效 - 准备对辅助端口的请求
    • 发送准备好的请求
    • 接收辅助端口的响应
    • 如果失败或超时 - 格式化业务响应并出现错误
    • 如果数据收集成功,为决策者准备指挥部
    • 呼叫决策者并返回事件/变更集/拒绝
    • 如果被拒绝 - 格式错误的业务请求
    • 如果被接受 - 为辅助端口准备另一组请求以执行决策:持久化到 DB、发送到 MQ、发射火箭等。
    • 等待辅助端口执行请求
    • 如果失败 - 格式化业务响应并出现错误
    • 如果正常 - 成功格式化业务响应

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

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

    【讨论】:

      【解决方案3】:

      域名:

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

      基本上,您不会将任何基础架构问题纳入您的领域,而是使用抽象。

      基础设施层,任何可能发生变化的东西,ORM,缓存,日志等......

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-03-24
        • 2015-02-23
        • 2014-10-15
        • 1970-01-01
        • 2011-10-09
        • 1970-01-01
        • 1970-01-01
        • 2020-01-21
        相关资源
        最近更新 更多