DDD: ссылка на сущность внутри совокупного корня по его идентичности

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

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

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

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

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

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

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

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

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

Как вы обходите это?

3 ответа

Решение

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

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

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

СУЩНОСТИ внутри границы имеют локальную идентичность, уникальную только в пределах АГРЕГАТА.

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

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

Order order = orderRepository.find(orderID);
order.updateQuantity(productID, 2);

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

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

Другие вопросы по тегам