【问题标题】:DDD Domain Specific/General InfrastructureDDD 特定领域/通用基础设施
【发布时间】:2011-11-03 14:00:49
【问题描述】:

关于域基础设施是否可以将它们视为:

  • 常规:如何发送电子邮件/读取配置文件等。
  • 具体说明:如何向新用户(域实体)发送激活码

如果我想到依赖项:

  • 通用基础架构(用于日志记录、通用异常等)

  • Specific Infrastructure General Infrastructure & Domain(获取IActivationCodeSender等基础设施相关的操作接口并能够实现一个 EmailActivationCodeSender 和一个 SmsActivationCodeSender)

在这种情况下,我的应用程序层将负责将所需的激活方法传递(DI 解析)到我的域实体,让我们说:

User.Register(IActivationCodeSender activationCodeSender)
{
   // Register user and generate activation code 1234
   ...
   activationCodeSender.Send(this, "1234");
}

这很糟糕吗?我应该改为在我的(通用)基础设施上工作以确保它支持以统一的方式发送短信/电子邮件(我担心这种情况可能会给我的通用基础设施带来复杂性)并删除这个特定的基础设施从某种意义上说,这样的层会将业务逻辑与基础设施相关的操作混合在一起?所以我会使用以下内容:

INotificationSender 的两个(通用)实现; EmailNotificationSenderSmsNotificationSender

User.Register(INotificationSender activationCodeSender)
{
   // Register user and generate activation code 1234
   ...
  // this.NotificationAddressInfo includes email address and mobile phone #

   activationCodeSender.Send(new Notification(this.NotificationAddressInfo, "Your activation code is 1234"));
}

【问题讨论】:

    标签: architecture dependency-injection domain-driven-design


    【解决方案1】:

    我建议您考虑使用具有这些基本原则的Dependency inversion principle(来自维基百科):

    1. 高级模块不应依赖于低级模块。两个都 应该依赖于抽象。
    2. 抽象不应依赖 根据细节。细节应该取决于抽象。

    所以我会将IActivationSender 之类的所有接口放在您的域中,然后在单独的基础架构项目中实现此接口。正如您所提到的,使用 DI 在您的应用程序服务(或域服务)中注入所需的实现。

    这样你就可以避免使用Douple dispatch pattern,将接口的实现直接传递给domain entity

    User.Register(INotificationSender activationCodeSender)

    取而代之的是:

    UserService.Register(user);

    UserService 可以是注入了正确 INotificationSender 的域服务。

    另一种解决问题的方法是使用域事件(请参阅Udi Dahans article)。按照这种模式,您的 User 实体将引发 INotificationSender 将依次订阅的“UserCreated”事件。这样,您就可以将发送通知消息的关注与用户实体分离。

    【讨论】:

      【解决方案2】:

      我建议在用户注册后创建订阅。并将您的代码生成、通知逻辑放在订阅聚合器中。它将控制需要发送的内容和顺序。如果失败怎么办等。您的通知可能是基础架构的一部分,因为它对您的域一无所知。只需获取电子邮件并发送出去。

      【讨论】:

        【解决方案3】:

        没有域基础设施。
        您的客户并不关心您将如何发送电子邮件。

        【讨论】:

        • 所以你认为基础设施项目不应该引用域项目,而应该独立于任何域工作(没有域基础设施)?
        • Arnis 关于没有域基础设施是正确的。任何基础设施接口都应移至应用程序级别及更高级别,您可以在其中拥有应用程序服务或 DomainEventHandler,而后者又可以通过其构造函数要求 INotificationSender。域应该 100% 不了解基础架构,即使是基础架构接口。
        猜你喜欢
        • 2021-01-08
        • 2018-07-03
        • 1970-01-01
        • 2010-11-25
        • 1970-01-01
        • 2015-12-07
        • 1970-01-01
        • 2014-06-16
        • 2010-10-16
        相关资源
        最近更新 更多