Ответ 1
Во-первых, должны ли ссылки между агрегатами всегда выполняться через значения ID, а не фактические ссылки на объекты?
Не совсем - хотя некоторые из них могут внести это изменение по соображениям производительности.
Например, если мне нужна информация о заказчике заказа, мне нужно будет взять CustomerId и передать его в ICustomerRepository, чтобы получить Клиента, а затем настроить объект Order, чтобы вернуть Клиенту прямо правильно?
Как правило, вы должны моделировать 1 сторону отношения (например, Customer.Orders
или Order.Customer
) для обхода. Другой может быть получен из соответствующего репозитория (например, CustomerRepository.GetCustomerFor(Order)
или OrderRepository.GetOrdersFor(Customer)
).
Не означает ли это, что OrderRepository должен был бы знать что-то о том, как создать клиента? Разве это не должно превышать то, что OrderRepository должен нести ответственность за...
OrderRepository
будет знать, как использовать ICustomerRepository.FindById(int)
. Вы можете ввести ICustomerRepository
. Некоторым может быть неудобно с этим, и выбрать, чтобы поместить его в сервисный уровень, - но я думаю, что это излишне. Там нет особых причин, по которым репозитории не могут знать и использовать друг друга.
Я смущен, потому что возвращение клиента напрямую кажется, что он упростит писать код в сравнении с моделью, и настроить его гораздо сложнее, если я использую ORM, например NHibernate. Тем не менее, я уверен, что это нарушит границы между совокупными корнями/репозиториями.
Совокупным корням разрешено удерживать ссылки на другие совокупные корни. Фактически, все разрешено содержать ссылку на совокупный корень. Совокупный корень не может содержать ссылку на неагрегатный корневой объект, который не принадлежит ему.
Например. Customer
не может содержать ссылку на OrderLines
- так как OrderLines
должным образом принадлежит как сущность в агрегированном корне Order
.
Во-вторых, где и как должен применяться каскад в отношении удаления для двух совокупных корней?
Если (и я подчеркиваю, что, поскольку это своеобразное требование), что на самом деле является прецедентом, это указывает на то, что Customer
должен быть вашим единственным агрегированным корнем. Однако в большинстве систем реального мира мы фактически не удалили бы Customer
, связанный с Order
, - мы можем отключить их, переместить их Order
в объединенные Customer
и т.д., Но не выходить и out удалите Order
s.
В то время как я не думаю, что это чистый DDD, большинство людей допустит некоторую снисходительность к следующему шаблону работы, где вы удаляете Order
, а затем Customer
(что не получится, если Order
все еще существовало). Вы даже можете сделать CustomerRepository
работу, если хотите (хотя я бы предпочел сделать ее более явным). Это также приемлемо, чтобы позволить осиротевшей Order
очищаться позже (или нет). Вариант использования здесь имеет значение.
Должен ли я вместо этого иметь службу CustomerManagment, которая обрабатывает удаление клиентов и связанных с ними ордеров, которые будут ссылаться как на IOrderRepository, так и на ICustomerRepository? В этом случае, как я могу быть уверен, что люди знают, как использовать Сервис, а не репозиторий для удаления Клиентов. Разве это просто до обучения их правильному использованию модели?
Я, вероятно, не стал бы маршрутом обслуживания для чего-то, столь тесно связанного с репозиторием. Что касается того, как убедиться, что служба используется... вы просто не ставите публичный Delete
на CustomerRepository
. Или вы бросаете ошибку, если удаление Customer
приведет к сиротству Order
s.