Я не уверен в использовании услуг для этого.
Насколько я понимаю, один из принципов DDD (который я сейчас читаю) состоит в том, что доменные объекты организованы в агрегаты и что при создании экземпляра агрегатного корня он может только непосредственно иметь дело с объектами в Агрегате (чтобы поддерживать четкое чувство ответственности).
Создание агрегата должно приводить в исполнение любые инварианты и т. Д.
Если взять пример класса Customer, то Customer может быть корневым элементом Aggregate, а другим классом в Aggregate может быть Address.
Теперь, если вы хотите создать нового клиента, вы можете сделать это, используя конструктор клиента или фабрику. Выполнение этого должно вернуть объект, который полностью функционирует в пределах Агрегатной границы (поэтому он не может работать с Продуктами, поскольку они не являются частью Агрегата, но могут обрабатывать Адреса).
База данных является второстепенной задачей и вступает в действие только для сохранения Агрегата в базе данных или извлечения его из базы данных.
Чтобы избежать непосредственного взаимодействия с базой данных, вы можете создать интерфейс репозитория (как обсуждалось), который с учетом экземпляра Customer (который включает ссылку на Address) должен иметь возможность сохранять Aggregate в базе данных.
Дело в том, что интерфейс репозитория является частью вашей доменной модели / слоя (реализация репозитория - нет). Другой фактор заключается в том, что хранилище, вероятно, должно в итоге вызывать тот же метод «создания», как если бы вы создавали новый объект (для поддержки инвариантов и т. Д.). Если вы используете конструктор, это достаточно просто, так как вы в конечном итоге вызовете конструктор, когда хранилище все равно «создаст» объект из данных.
Прикладной уровень может напрямую связываться с доменом (включая интерфейс репозитория).
Итак, если вы хотите создать новый экземпляр объекта, вы можете, например,
Customer customer = new Customer();
Если приложению необходимо извлечь экземпляр клиента из хранилища, я не могу представить себе особой причины, по которой оно не должно вызывать ...
Customer customer = _custRepository.GetById(1)
или ...
Customer customer = _custRepository.GetByKey("AlanSmith1")
В конечном итоге он получит экземпляр объекта Customer, который функционирует в пределах своих собственных ограничений и правил, как если бы он создал новый объект Customer напрямую.
Я думаю, что службы должны быть зарезервированы для случая, когда «вещь», с которой вы пытаетесь работать, просто не является объектом. Большинство правил (ограничений и т. Д.) Могут быть написаны как часть самого предметного объекта.
Хороший пример - в DDD Quickly, который я читаю в данный момент. Там у них есть ограничение на объект Книжная полка, в результате чего вы можете добавить только столько книг, сколько может содержать полка.
Вызов метода AddBook для объекта BookShelf проверяет наличие свободного места перед добавлением книги в коллекцию объектов BookShelf. Простой пример, но бизнес-правило применяется самим объектом домена.
Я не говорю, что все вышесказанное, кстати, правильно! Я сейчас пытаюсь все обдумать!