如何在DDD中正确设计模型的计算字段?

时间:2015-11-11 11:46:54

标签: design-patterns architecture domain-driven-design

我正在成为DDD的忠实粉丝。所以,我正在考虑将它正确地应用到我开发的当前系统中。

假设我们有两个聚合根:OrderUserOrder有两个属性,引用Userownercontractor。所有者创建了Order,承包商履行了它。

业主可以评估承包商履行Order的质量。我们有一个Feedback实体,连接到Order,包含评级。

现在,User对象包含每个用户在其履行的订单中的平均评分。这部分让我感到困惑。

User评分不仅仅是一个静态属性,实际上是Feedbacks中所有评分的平均值。在Order附加Feedback时,它会被更改(需要重新计算)。

目前我有一些封装域逻辑的服务:OrderServiceUserService(我知道这实际上不符合DDD,但我稍后会重构)。当OrderService收到将反馈附加到订单的命令时,它会发出OrderFeedbackAttachedEvent,UserService会侦听以重新计算用户评级。

对我不满意的是,关于Order聚合根的知识现在已泄露到UserService中。而且我没有看到逃避它的方法。我开始认为应该有一些模式来处理这种情况。

评级似乎是用户的完美属性。但事实上,它不是一个静态的,持久的价值,而是基于其他对象数据计算的东西,让我怀疑。

评级本身也不是一个实体。它既不是价值对象。我想知道,在DDD中它是什么?如何在不牺牲性能和易用性的情况下对系统中的评级(或任何其他可计算值)进行建模?

2 个答案:

答案 0 :(得分:7)

看起来你可能至少有2个分离的有界上下文:一个用于排序,另一个用于反馈。

Aknowleging Bounded Contexts允许你看到同一物理事物的不同抽象:在“订单”上下文中,Order似乎是一个合法的Aggregate,但它可能是“反馈”BC中的一个Value Object,它会在那里持有订单ID(该值来自BC通过事件的订单)。

以下是提案:

enter image description here enter image description here

使用此模型,您可以在承包商汇总的事件处理程序中处理反馈汇总中的“FeedbackEmitted”事件时计算承包商的平均评级

希望这会有所帮助:)

答案 1 :(得分:2)

公平地说,从另一个AR或另一个BC发出的事件不是泄漏。在我看来,User AR处理OrderFeedbackGiven事件没有问题。如果Feedback VO是事件的一部分,那么客户端不需要依赖任何其他事件来处理事件。有一个反馈有限的上下文可能会更清晰,但我不会为此实现一个完整的BC,否则你会爆发微型BC ......

  

我很担心这一事实,在给出反馈后,所有   必须汇总反馈以计算用户评级。这创造了一个   从用户到订单的依赖(调用订单存储库以获取   当事件被捕获时,来自用户服务的评级)。这样可以,做什么   你觉得呢?

我认为如果你那样做并不重要。应用程序服务层整体上取决于域层。但是,由于您可以计算moving cumulative average

,因此根本不需要这样做

E.g。其中this.ordersFeedbackAvgMovingAvg值对象,用于跟踪平均值以及计算的数据点数。

when(OrderFeedbackGiven feedback) { this.ordersFeedbackAvg = this.ordersFeedbackAvg.cumulate(feedback.mark); }