Специфичная для домена DDD / Общая инфраструктура

#architecture #dependency-injection #domain-driven-design

#архитектура #внедрение зависимостей #дизайн, управляемый доменом

Вопрос:

Что касается инфраструктуры домена, можно ли думать о них как:

  • Общие сведения: Как отправить электронное письмо / прочитать файл конфигурации и т. Д..
  • Специфика: как отправить код активации новому пользователю (объекту домена)

Где, если я думаю о зависимостях:

  • Домен <Ссылки> Общая инфраструктура (для ведения журнала, общих исключений и т. Д.)

  • Специфическая инфраструктура < Ссылки> Общая инфраструктура и домен (чтобы получить связанные с инфраструктурой операционные интерфейсы, такие как IActivationCodeSender, и иметь возможность реализовать EmailActivationCodeSender и SmsActivationCodeSender)

В этом случае мой прикладной уровень будет отвечать за передачу (разрешенный DI) желаемого метода активации моему объекту домена, скажем:

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

Это плохо? должен ли я вместо этого работать над своим (общим) Инфраструктура, чтобы убедиться, что она поддерживает унифицированную отправку sms / электронной почты (боюсь, такие случаи могут усложнить мою общую инфраструктуру) и удалить эту конкретную инфраструктуру в том смысле, что такой уровень будет смешивать бизнес-логику с операциями, связанными с инфраструктурой? поэтому вместо этого я бы использовал следующее:

Две (общие) реализации для 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"));
}
  

Ответ №1:

Я бы посоветовал вам рассмотреть возможность использования принципа инверсии зависимостей, который имеет эти основные принципы (из Википедии):

  1. Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.
  2. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Поэтому я бы разместил все интерфейсы, подобные IActivationSender вашему домену, а затем реализовал этот интерфейс в отдельном инфраструктурном проекте. Как вы упомянули, используйте DI для внедрения желаемой реализации в вашу службу приложений (или в службу домена).

Таким образом, вы можете избежать использования шаблона двойной отправки, когда вы передаете реализацию интерфейса непосредственно в domain entity :

User.Register(INotificationSender activationCodeSender)

И вместо этого есть что-то вроде:

UserService.Register(user);

Где UserService может быть доменной службой с введенным правильным INotificationSender.

Совершенно другим способом решения проблемы может быть использование событий домена (см. Статью Уди Даханса). Следуя этому шаблону, ваша пользовательская сущность вызовет событие «UserCreated», на которое INotificationSender, в свою очередь, подпишется. Таким образом, вы отделяете проблему отправки уведомлений от объекта User.

Ответ №2:

Я бы предложил создать подписку после регистрации пользователя. И поместите свою генерацию кода, логику уведомлений в агрегатор подписки. Он будет контролировать, что нужно отправить и какова последовательность. что делать, если сбой и т. Д. И ваше уведомление может быть частью инфраструктуры, поскольку оно может ничего не знать о вашем домене. Просто получите электронное письмо и отправьте.

Ответ №3:

Инфраструктуры домена нет.
Ваш клиент не заботится о том, как вы собираетесь отправлять электронные письма.

Комментарии:

1. Итак, вы считаете, что инфраструктурные проекты не должны ссылаться на доменные проекты, а скорее работать независимо от какого-либо домена (без инфраструктуры домена)?

2. Арнис прав в отношении отсутствия инфраструктуры домена. Любой интерфейс инфраструктуры должен быть перемещен на уровень приложения и выше, где у вас может быть служба приложений или обработчик DomainEventHandler, который, в свою очередь, может потребовать INotificationSender через его конструктор. Домен должен на 100% не знать инфраструктуры, даже об интерфейсах инфраструктуры.