DDD:通过其标识引用聚合根内的实体

时间:2011-09-05 16:19:38

标签: language-agnostic domain-driven-design entity identity aggregateroot

当我们只有他们的身份来时,我一直在寻找正确的方法来引用聚合根中的实体来自URL参数。我问previous question最后关注值对象,所以我从这里开始另一个例子。

假设我们要修改OrderLine内的Order

  • 用户转到一个页面,在该页面中,他可以看到订单摘要及其所有订单行。
  • 用户点击订单热线旁边的修改按钮。
  • 他被定向到edit-order-line?orderId=x&orderLineId=y

现在,如果我需要更新OrderLine中的数量,我可以这样做:

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

但是,我对将责任留给订单以便通过Id检索部分内容的想法感到不自在。我对这个主题的看法是,在域内,我们应该与对象交谈,而不是与Ids交谈。 Ids不是无所不在的语言的一部分,我相信它们应该存在于域之外,例如在Controller中。

我会对以下内容更有信心:

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

虽然我不喜欢直接与实体管理器交互的想法。我觉得我绕过了Repository和Aggregate Root职责(因为我可以,可能直接与OrderLine交互)。

你如何解决这个问题?

3 个答案:

答案 0 :(得分:12)

在我看来,这种方法没有错:

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

orderLineId是“本地身份”。它特定于聚合根,并且在它之外没有意义。您不必将其称为“id”,它可以是“订单行号”。来自Eric Evan's书:

  

边界内的ENTITIES具有本地身份,仅在其中具有唯一性   AGGREGATE。

     

...只有AGGREGATE根可以直接使用数据库查询获得。必须通过遍历关联找到所有其他对象。

答案 1 :(得分:1)

OrderLineId究竟是什么?它毫无意义。您正在更新PRODUCT的数量,以及应该用作ID的内容。

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

答案 2 :(得分:0)

聚合根绑定到上下文,在您的上下文中,订单 AR,因此可以直接更新它,因为您直接公开它,如果该代码影响他们应该在订单AR中居住的其他实体。

如果你想要更纯粹的方法,你必须在AR中创建一个findByOrderId并完全加载它或在你的应用程序中公开OrderLine和OrderId(然后使用你的第二种方法)。