Давайте представим, что у меня есть Группы и Пользователи, и когда пользователь хочет присоединиться к группе, я вызываю метод groupsService.AddUserToGroup (group, user). В DDD я должен сделать group.JoinUser (пользователь), который выглядит довольно хорошо.
Но DDD также рекомендует вам использовать (не сохраняющие состояние) сервисы для выполнения задач, если выполняемая задача слишком сложна или не вписывается в модель объекта. Это нормально, чтобы иметь сервисы на уровне домена. Но услуги на уровне домена должны включать только бизнес-логику. Внешние задачи и логика приложения (например, отправка электронной почты), с другой стороны, должны использовать доменную службу на уровне приложений, в которую, например, может входить отдельная (прикладная) служба.
Проблема появляется, если у меня есть некоторые правила проверки для добавления пользователя ...
Правила валидации принадлежат модели домена! Они должны быть заключены в доменные объекты (объекты и т. Д.).
... или некоторые внешние задачи должны быть запущены при добавлении пользователя в группу. Наличие этих задач приведет к тому, что у сущности будут внешние зависимости.
Хотя я не знаю, о какой внешней задаче вы говорите, я предполагаю, что это что-то вроде отправки электронного письма и т. Д. Но на самом деле это не является частью модели вашего домена. Он должен жить на прикладном уровне и передаваться туда imho. У вас может быть служба на уровне приложений, которая работает с доменными службами и объектами для выполнения этих задач.
Но тот факт, что сущность зависит от некоторых внешних служб / классов, не кажется мне таким хорошим и «естественным».
Это неестественно и не должно происходить. Сущность не должна знать о том, что не входит в ее обязанности. Услуги должны использоваться для организации взаимодействия сущностей.
Как правильно бороться с этим в DDD?
В вашем случае отношения должны быть двунаправленными. Вступает ли пользователь в группу или группа принимает пользователя, зависит от вашего домена. Пользователь присоединяется к группе? Или пользователь добавлен в группу? Как это работает в вашем домене?
В любом случае, у вас двунаправленные отношения, и вы можете определить количество групп, к которым пользователь уже принадлежит, в совокупности пользователей. Передача пользователя группе или группы пользователю технически тривиальна после определения ответственного класса.
Затем проверка должна быть выполнена объектом. Все это вызывается службой прикладного уровня, которая также может выполнять технические функции, такие как отправка электронных писем и т. Д.
Однако, если логика проверки действительно сложна, лучшим решением может быть служба домена. В этом случае инкапсулируйте бизнес-правила, а затем вызовите их из уровня приложения.
Я бы подошел к проблеме проверки так: создайте доменную службу с именем
MembershipService
:Субъекту Группы необходимо ввести
IMemberShipService
. Это можно сделать на уровне класса или на уровне метода. Предположим, мы делаем это на уровне метода.Служба приложения:
GroupService
может быть внедрена сIMemberShipService
помощью конструктора, который затем может быть переданJoinUser
методуGroup
класса.источник