DDD域特定/通用基础设施

时间:2011-11-03 14:00:50

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

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

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

如果我想到依赖关系:

  • <参考文献> 一般基础设施(用于记录,一般例外等)

  • 特定基础设施<参考文献> General Infrastructure&域(获取与基础设施相关的操作界面,如 IActivationCodeSender ,并能够实现 EmailActivationCodeSender & a SmsActivationCodeSender

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

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

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

INotificationSender 的两个(常规)实现; EmailNotificationSender SmsNotificationSender

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"));
}

3 个答案:

答案 0 :(得分:1)

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

  
      
  1. 高级模块不应依赖于低级模块。都   应该取决于抽象。
  2.   
  3. 抽象不应该依赖   细节。细节应取决于抽象。
  4.   

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

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

  

User.Register(INotificationSender activationCodeSender)

而是有类似的东西:

UserService.Register(user);

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

解决问题的另一种方法可能是使用域事件(请参阅Udi Dahans article)。遵循此模式,您的用户实体将引发INotificationSender将订阅的“UserCreated”事件。这样您就可以解除从用户实体发送通知消息的顾虑。

答案 1 :(得分:0)

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

答案 2 :(得分:0)

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