代码之家  ›  专栏  ›  技术社区  ›  James

如何处理CQRS架构中的命令端影响?

  •  1
  • James  · 技术社区  · 10 年前

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

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

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

    我们的节点聚合有一个不变量,它规定排名不能设置为低于特定值(我们称之为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 回复  |  直到 10 年前
        1
  •  3
  •   Alexander Langer    10 年前

    乍一看(考虑到节点/排名内容很可能被简化),“排名”属性的聚合边界可能被错误放置,特别是如果一个节点的排名影响其兄弟节点的排名,这显然是跨越AR边界。

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

    如果“排名”具有更复杂的含义,您可以尝试将父节点中的排序与单个节点的“排名”属性与saga分离(即,每当排名更改时发送重新排序命令)。