Design patterns 如何正确设计模型&x27;是以DDD为单位的计算字段吗?

Design patterns 如何正确设计模型&x27;是以DDD为单位的计算字段吗?,design-patterns,architecture,domain-driven-design,Design Patterns,Architecture,Domain Driven Design,我正在成为一个超级粉丝。因此,我正在考虑将它正确地应用到我目前开发的系统中 假设我们有两个聚合根:Order和User订单有两个属性,引用用户:所有者和承包商。业主创建了一份订单,承包商完成了该订单 业主可以对承包商履行订单的质量进行评分。因此我们有一个反馈实体,连接到订单,包含评级 现在,User对象包含每个用户完成订单的平均评分。这部分让我有点困惑 用户评级不仅仅是一个静态属性,实际上是整个反馈的所有评级的平均值。并且在订单附加了反馈的那一刻更改(需要重新计算) 目前,我有一些封装域逻辑的服

我正在成为一个超级粉丝。因此,我正在考虑将它正确地应用到我目前开发的系统中

假设我们有两个聚合根:
Order
User
<代码>订单有两个属性,引用
用户
所有者
承包商
。业主创建了一份
订单
,承包商完成了该订单

业主可以对承包商履行
订单
的质量进行评分。因此我们有一个
反馈
实体,连接到
订单
,包含评级

现在,
User
对象包含每个用户完成订单的平均评分。这部分让我有点困惑

用户
评级不仅仅是一个静态属性,实际上是整个
反馈的所有评级的平均值
。并且在
订单
附加了
反馈
的那一刻更改(需要重新计算)

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

令我不满意的是,关于订单聚合根的知识现在泄漏到了UserService中。我看不到逃避的方法。我开始认为应该有一些模式来处理此类案件

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


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

看来您可能至少有两个独立的有界上下文:一个用于排序,另一个用于反馈

Aknowleging Bounded context允许您查看同一物理对象的不同抽象:在“orders”上下文中,Order似乎是一个合法的聚合,但它可以是“feedback”BC中的一个值对象,它将保存Order id(该值通过事件来自Order BC)

以下是一项建议:

使用此模型,您可以在承包商聚合的事件处理程序中处理来自反馈聚合的“反馈发出”事件时,计算承包商的平均评级


希望这有帮助:)

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

我担心的是,在给出反馈后,所有 必须汇总反馈以计算用户评级。这就产生了一个 从用户到订单的依赖关系(调用订单存储库获取 捕获事件时,来自用户服务的评级)。这样行吗,你怎么办 你觉得呢

我想你那样做也没关系。应用程序服务层作为一个整体依赖于域层。但是,根本不需要这样做,因为您可以计算

例如,其中
this.ordersFeedbackAvg
是一个
MovingAvg
值对象,用于跟踪平均值及其计算数据点的数量

何时(订单反馈给定反馈){
this.ordersFeedbackAvg=this.ordersFeedbackAvg.cumulate(feedback.mark);

}

您使用了什么来创建图表?@DavidOsborne:我使用了@Mehdi中记录的语法。Thx的神奇工具@plalx我担心的是,在给出反馈后,所有反馈都必须汇总以计算用户评分。这将创建从用户到订单的依赖关系(在捕获事件时,调用订单存储库从用户服务获取评级)。这样可以吗,你觉得怎么样?谢谢你的好主意@VladislavRastrusny我的例子是不完整的,因为它没有为单个订单建模平均值,我也没有对语言进行太多的关注,但你明白了。@VladislavRastrusny我在回答中没有提到的另一个方面是并发性。您真的需要
用户
实体来保存反馈平均值吗?现在,任何涉及
用户
AR的其他命令都可能与处理
OrderFeedbackGiven
事件同时发生冲突。由于此移动平均值最终是一致的,因此您可以创建另一个AR来仅对此负责,这将减少
用户
AR上的争用。是否有任何原因说明此平均值是
用户
AR的一部分?您是否在该AR处理的任何命令中使用了该信息?请不要忘记,不必对域模型进行查询,因此可以将来自多个AR的数据聚合为一个视图。您的事件是处理单线程事件还是可以同时处理多个事件?使用最终一致性的另一种策略是一次接受多个请求,但以单线程方式处理它们。因此,如果您有一个用于反馈平均值的AR,您甚至不需要使用这种方法进行锁定。@VladislavRastrusny很棒!那么我想我给你的最好的建议是,当你设计你的对象模型时,你应该完全忘记查询。域模型旨在通过创建作为事务边界的AR来实现命令和保护不变量。在路上