#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:
Я бы посоветовал вам рассмотреть возможность использования принципа инверсии зависимостей, который имеет эти основные принципы (из Википедии):
- Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.
- Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Поэтому я бы разместил все интерфейсы, подобные IActivationSender
вашему домену, а затем реализовал этот интерфейс в отдельном инфраструктурном проекте. Как вы упомянули, используйте DI для внедрения желаемой реализации в вашу службу приложений (или в службу домена).
Таким образом, вы можете избежать использования шаблона двойной отправки, когда вы передаете реализацию интерфейса непосредственно в domain entity
:
User.Register(INotificationSender activationCodeSender)
И вместо этого есть что-то вроде:
UserService.Register(user);
Где UserService может быть доменной службой с введенным правильным INotificationSender.
Совершенно другим способом решения проблемы может быть использование событий домена (см. Статью Уди Даханса). Следуя этому шаблону, ваша пользовательская сущность вызовет событие «UserCreated», на которое INotificationSender, в свою очередь, подпишется. Таким образом, вы отделяете проблему отправки уведомлений от объекта User.
Ответ №2:
Я бы предложил создать подписку после регистрации пользователя. И поместите свою генерацию кода, логику уведомлений в агрегатор подписки. Он будет контролировать, что нужно отправить и какова последовательность. что делать, если сбой и т. Д. И ваше уведомление может быть частью инфраструктуры, поскольку оно может ничего не знать о вашем домене. Просто получите электронное письмо и отправьте.
Ответ №3:
Инфраструктуры домена нет.
Ваш клиент не заботится о том, как вы собираетесь отправлять электронные письма.
Комментарии:
1. Итак, вы считаете, что инфраструктурные проекты не должны ссылаться на доменные проекты, а скорее работать независимо от какого-либо домена (без инфраструктуры домена)?
2. Арнис прав в отношении отсутствия инфраструктуры домена. Любой интерфейс инфраструктуры должен быть перемещен на уровень приложения и выше, где у вас может быть служба приложений или обработчик DomainEventHandler, который, в свою очередь, может потребовать INotificationSender через его конструктор. Домен должен на 100% не знать инфраструктуры, даже об интерфейсах инфраструктуры.