您如何处理CQRS架构中的命令副作用?

时间:2014-07-22 13:48:15

标签: domain-driven-design distributed cqrs

我们开始在我们的系统中找到一些场景,其中针对聚合的命令的结果可以影响其他相关聚合。

为了演示这个问题,请考虑一个树结构,其中我们有拥有兄弟节点的节点。每个节点都有一个排名,以确定它们在用户界面中的显示顺序,即

Node 1 | Ranking = 10
Node 2 | Ranking = 11
Node 3 | Ranking = 12
Node 4 | Ranking = 13
Node 5 | Ranking = 14

我们的Node聚合有一个不变量,它规定排名不能低于特定值(让我们称之为10)。如果将排名设置为低于此值,则会导致重新计算所有兄弟节点(包括相关节点)。为了简单起见,假设计算只是基于兄弟姐妹排名的两倍来计算排名

Node 1 | Ranking = 9 (cannot be accepted, reset to 50)
Node 2 | Ranking = 100
Node 3 | Ranking = 200
Node 4 | Ranking = 400
Node 5 | Ranking = 800

关键是,针对一个聚合的命令会导致对另一个聚合(或在这种情况下为多个)的更改。

到目前为止采取的方法是在通往域的途中拦截这些命令,"修复"他们和然后发送它们。所以在上面的示例场景中

  • 我们从客户
  • 收到ChangeNodeRankingCommand
  • 我们验证命令,即新排名是否高于10
  • 如果该命令有效,则将其发送到域
  • 如果命令无效,我们会查询读取方以提取所有受影响的聚合ID
  • 我们使用调整后的排名
  • 为每个聚合(包括有问题的聚合)创建命令
  • 我们将这些命令发送到域并丢弃原始

这很好,但有一些问题

  • 我们一直在处理可能导致问题的陈旧数据(尝试更新随后删除的实体等)。
  • 这个东西出现是域逻辑,因此应该由域处理

选择这样做的原因纯粹是从查询的角度来看,我们在域中使用Event Sourcing因此加载相关的聚合并不是微不足道的(鉴于其性质)我们的活动商店。)

这是一种合理的方法,还是我完全错过了一招?

1 个答案:

答案 0 :(得分:3)

乍一看(鉴于节点/排名内容很可能是简化的),似乎您的“排名”属性的聚合边界可能会被错误放置,特别是如果一个节点的排名影响其排名兄弟姐妹,明显越过AR边界。

在典型的树结构中(在数学意义上),所有兄弟姐妹的可被视为负责其子女的排序。在此模型中,如果您随后向这些孩子的父母发送ChangeNodeRankingCommand,则所有孩子的重新排名都会在AR上进行。

如果“排名”具有更复杂的含义,您可以尝试将父节点中的排序与具有传奇的各个节点的“排名”属性解耦(即,每当发送重新排序命令时)排名变化)。