【问题标题】:DDD Call Adapter from Within Domain Object来自领域对象的 DDD 调用适配器
【发布时间】:2022-11-18 06:46:27
【问题描述】:

我正在使用域驱动设计实现六边形架构。

我有一个名为“Address”的值对象,它有一个“validate()”方法。 我希望为我域内的地址提供一个默认验证提供程序,但也允许外部用户提供一个覆盖的验证程序。

所以我创建了一个 AddressValidationAdapter 接口,可以让外界以“依赖倒置”的方式实现。

我的问题是 - 从我的 Address 类中调用我的 AddressValidationAdapter 的最佳方式是什么?

  • 我是否需要将其作为依赖项添加到其构造函数中?
  • 我应该使用某种全局/静态上下文吗?
  • 我是否应该使用事件驱动方法在我的域中发布“ValidationEvent”并订阅验证成功通知?
  • 我应该创建一个协调一切的服务吗? (好像不是很像DDD)

非常感谢你的想法。 此致 亚历克斯

【问题讨论】:

    标签: domain-driven-design hexagonal-architecture


    【解决方案1】:

    你提到领域驱动设计,这是一种要求所有与业务相关的代码都放在领域层,以及所有非业务相关的代码,以走出该领域层。除此之外,DDD 更关心你如何设计和发展你的业务模型,而不是应用程序架构。 DDD 概念的作者指出它可以与任何软件架构一起使用。

    你还提到六角形建筑,它解决了软件架构问题,并且对您如何构建代码有更多限制。六边形架构在应用程序中定义了 3 个同心层:

    • 领域层验证状态变化值不违反业务规则;
    • 端口层是基础架构交互的业务表示;
    • 适配层实现与外部基础设施的实际通信。

    Hexagonal Architecture 还声明类型引用应该向内,这意味着端口不允许引用适配器,并且域模型不允许引用其他层。一个好的做法是禁止跨不同适配器的直接引用。但是,这在您的情况下并不是什么大问题。

    地址验证绝对不是适配器层问题,因为它与您的应用程序如何与外部基础设施或数据结构交互无关。这意味着地址验证不应作为适配器,在六角形建筑的意义上。出于同样的原因,它也不是一个港口。地址验证应该在领域层,因为业务规则验证是域层(六边形架构)的目的,所有与业务相关的代码都应该放在域层(DDD)中。

    但是,DDD 和六边形架构都没有说明您应该如何在内部构建领域层,所以这取决于您。如果您希望您的应用程序使用不同的验证实现,您可能希望在 cunjunction 中使用 adapter pattern 和依赖注入库。请注意,这里的“适配器”指的是一种软件工程设计模式,它启发了适配器层的六边形架构概念,但完全独立于它。

    由于领域层的目的是验证状态变化数据,因此除了验证规则实现和数据结构之外,应该只有很少的代码。如果将后者移至验证器类,则领域模型对象本身就没有什么可写的了。您可能会以这种方式以 anemic domain model 结尾。您可能需要考虑实现 Always Valid State 域模型,其中验证规则直接在域模型的设置器和构造函数中实现。

    如果您因为需要检索外部数据来进行实际验证而编写了一个适配器类,这很好地证明了您的域模型缺少信息并且应该扩展,而不是违反六边形架构约束。

    【讨论】:

    • 您好,感谢您的详细解答!它确实帮助我弄清楚了一些概念!然而,就我而言,我需要允许外部客户端覆盖验证。我正在创建一个将由客户集成的应用程序模块。如果他们愿意,我希望允许客户覆盖验证逻辑。这就是为什么在我的例子中我认为验证是一个端口。你对如何以最 DDD 的方式做到这一点有什么想法吗?
    【解决方案2】:

    我是否需要将其作为依赖项添加到其构造函数中?

    绝对没有!值对象是数据,您正在为它进行序列化/反序列化,让自己陷入困境

    我应该使用某种全局/静态上下文吗?

    不确定你的意思,但全局/静态上下文很可怕,并行完成多个验证怎么样?

    我应该使用事件驱动的方法在我的域中发布“ValidationEvent”并订阅验证成功通知吗?

    领域事件与实体状态变化相关,当你进行验证时没有任何变化

    我应该创建一个服务来协调一切吗? (好像不是很像DDD)

    它可能是...

    但也允许外部用户提供一个覆盖的验证器。

    我很好奇这方面的细节,为什么外部用户需要不同的验证?
    Address 是否有某种需要始终检查的通用验证,但不同的用例有更严格的规则?
    如果是这样,为什么 Address 本身需要知道它们?它只是一个值! Integer 只知道它必须是一个数字,如果在某些用途中你需要它在一个值的范围内,它是你添加到它的东西,但它不知道

    DI/IoC 方法很好,我想你可以这样做:

    class Address {
        ....
    
        validate(AddressValidationAdapter customValidation) {
             // generic validation then...
             customValidation.validate(whatAreYouPassingHere)
        }
    }
    

    无论您使用的是whatAreYouPassingHere,代码都不能:

    Address address = ...
    address.validate(customValidator)
    

    只是从地址中读取所需的值并进行自己的验证?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-03
      • 1970-01-01
      • 2016-12-06
      • 1970-01-01
      • 2017-02-01
      • 1970-01-01
      • 2011-05-17
      • 2022-10-17
      相关资源
      最近更新 更多