DDD: ссылка на объект внутри совокупного корня по его идентификатору

Я застрял в поиске правильного способа ссылки на объекты, расположенные внутри совокупного корня, когда мы получили их идентификаторы только из параметров URL . Я задал предыдущий вопрос, который в итоге сосредоточился на объектах значений < / em>, поэтому я начну с другого примера.

Допустим, мы хотим изменить OrderLine внутри Order:

  • Пользователь переходит на страницу, где он может видеть сводку заказа вместе со всеми его строками заказа.
  • Пользователь нажимает кнопку изменить рядом со строкой заказа.
  • Его направляют к edit-order-line?orderId=x&orderLineId=y

Теперь, если мне нужно обновить количество в OrderLine, я могу сделать:

Order order = orderRepository.find(orderId);
order.updateQuantity(orderLineId, 2);

Однако мне не очень нравится идея передать Ордену ответственность за извлечение частей себя с помощью Id. Я считаю, что внутри домена мы должны просто разговаривать с объектами, а не с идентификаторами. Идентификаторы не являются частью повсеместного языка, и я считаю, что они должны находиться вне домена, например, в контроллере.

Я бы чувствовал себя увереннее с чем-то вроде:

Order order = orderRepository.find(orderId);
OrderLine orderLine = em.find(OrderLine.class, orderLineId);
order.updateQuantity(orderLine, 2);

Хотя мне тоже не нравится идея прямого взаимодействия с Entity Manager. Мне кажется, что я обхожу обязанности репозитория и агрегированного корня (потому что я мог потенциально взаимодействовать с OrderLine напрямую).

Как вы работаете с этим?


person BenMorel    schedule 05.09.2011    source источник


Ответы (3)


На мой взгляд, в таком подходе нет ничего плохого:

Order order = orderRepository.find(orderId);
order.updateQuantity(orderLineId, 2);

orderLineId - это «местная идентичность». Он специфичен для агрегированного корня и не имеет смысла вне его. Необязательно называть его «id», это может быть «номер строки заказа». Из книги Эрика Эвана:

ENTITIES внутри границы имеют локальную идентичность, уникальную только в AGGREGATE.

... только ОБЩИЕ корни могут быть получены напрямую с помощью запросов к базе данных. Все остальные объекты должны быть найдены путем обхода ассоциаций.

person Dmitry    schedule 05.09.2011
comment
Я согласен - orderLineId не обязательно должен означать ваш идентификатор БД, это может быть что угодно, что однозначно определяет порядок в этом единственном агрегате (порядковый номер строки или агрегированный код в форме orderNo / LineNo). Заказчик обязан найти конкретную строку по этому идентификатору. - person kstaruch; 05.09.2011
comment
Не приведет ли этот подход к раздуванию интерфейса AR, если бы у AR было всего 2 объекта с 2 методами в каждом, AR потребовалось бы иметь 4 метода для поддержки объектов. Является ли это идеальным подходом? - person Sudarshan; 20.05.2013
comment
Это зависит от обстоятельств, и можно утверждать, что у вас уже есть проблема, когда у вас такой большой агрегат. Это может быть просто признаком того, что вам нужно пересмотреть свой дизайн в сторону меньшего агрегата, см. dddcommunity.org/library / vernon_2011 - person Dmitry; 20.05.2013

OrderLineId - это что именно? Это не имеет значения. Вы обновляете количество ПРОДУКТА, и это то, что следует использовать в качестве идентификатора.

Order order = orderRepository.find(orderID);
order.updateQuantity(productID, 2);
person nilskp    schedule 20.11.2011
comment
Это серьезное возражение, хотя в нашем приложении у вас может быть несколько раз один и тот же Продукт в вашей корзине покупок с разными выбранными параметрами (подумайте о зеленой футболке и красной футболке; если я хочу обновить конкретно количество зеленой футболки, я не хочу передавать полный набор параметров, чтобы соответствовать правильной строке заказа: цвет, размер, ... и поэтому передача orderLineId - это то, что для меня имеет наибольший смысл на данный момент ). - person BenMorel; 21.11.2011
comment
Справедливо. Хотя я, вероятно, все же выбрал бы более естественный ключ, такой как productID + все остальное, что делает его уникальным. Но, конечно, OrderLineId все равно будет работать. - person nilskp; 06.12.2011

Совокупные корни привязаны к контексту, в вашем контексте Порядок является AR, поэтому можно обновить его напрямую, поскольку вы открываете его напрямую, если этот код влияет на другие объекты они должны жить в Ордене AR.

Если вам нужен более пуристический подход, вам нужно либо создать findByOrderId в AR и загрузить его полностью, либо предоставить OrderLine и OrderId в своем приложении (затем используйте второй подход).

person Francisco Aquino    schedule 05.09.2011
comment
Я думаю, что вопрос Бенджамина о том, как лучше всего перейти от совокупного корня к строке заказа внутри него, которую он хочет обновить. Итерация кода приложения по строкам порядка, кажется, пересекает черту кода приложения. - person Eric Farr; 05.09.2011
comment
Спасибо за разъяснения, признаюсь, я не использую «уникальный только в совокупности» Дмитрий, опубликованный выше, и теперь задаюсь вопросом, сталкивался ли я когда-нибудь с такой реализацией. - person Francisco Aquino; 07.09.2011