Во-первых, должны ли ссылки между агрегатами всегда выполняться через значения идентификаторов, а не фактические ссылки на объекты?
Не совсем - хотя некоторые могут внести это изменение по соображениям производительности.
Например, если мне нужны подробности о клиенте Заказа, мне нужно взять 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
должен быть вашим единственным совокупным корнем.В большинстве реальных систем, однако, мы не будем на самом деле удалять a Customer
, которые связаны с Order
с - мы можем их деактивировать, перемещать их Order
s в объединенный Customer
и т. д. - но не извлекайте и удаляйте Order
s.
При этом, хотя я и не думаю, что это чисто DDD, большинство людей допускают некоторую снисходительность в следовании образцу единицы работыгде вы удаляете Order
s, а затем Customer
(который потерпит неудачу, если Order
s все еще существует).Вы можете даже сделать CustomerRepository
делать работу, если хотите (хотя я бы предпочел сделать это более явным самостоятельно).Также допустимо, чтобы осиротевшие Order
s были убраны позже (или нет).Вариант использования имеет здесь все значение.
Должен ли я вместо этого иметь службу CustomerManagment, которая обрабатывает удаление клиентов и связанных с ними заказов, которые будут ссылаться как на IOrderRepository, так и на ICustomerRepository?В таком случае, как я могу быть уверен, что люди знают, как использовать Сервис, а не репозиторий для удаления Клиентов.Это только из-за обучения их правильному использованию модели?
Я, вероятно, не пошел бы по пути обслуживания для чего-то столь тесно связанного с хранилищем.Что касается того, как убедиться, что служба используется ... вы просто не ставите публичный Delete
на CustomerRepository
.Или вы выдаваете ошибку, если удаление Customer
оставит сиротами Order
s.