控制器级别的 CQRS 和共享逻辑

时间:2021-02-04 21:53:56

标签: cqrs clean-architecture

我正在使用 CQRS 和 MediatR 库,试图学习一些最佳实践。我发现很难理解如何将所有业务逻辑拆分为命令和查询。

这是一个例子:

我有一个 Address 实体,我已经创建了两个命令和一个查询:InsertAddressCommandUpdateAddressCommandGetAddressByUserIdQuery

控制器中有端点负责执行插入、更新或负责按用户 ID 返回地址。

还有一个名为 UpdateOrInsertAddress 的端点,它重用了 2 个命令和 1 个查询:首先通过用户 id 获取地址并根据结果执行插入或更新。

到目前为止一切顺利。

现在,还有另一个端点 SubmitPurchaseOrder 正在接收一个更大的对象。与购买相关的所有信息都会立即收到。送货地址和账单地址是发布对象的一部分。

然后我想重用 UpdateOrInsertAddress 中的逻辑,因为所有逻辑都已经存在(而且我被教导重用代码);但由于 UpdateOrInsertAddress 是一个端点,我无法从另一个端点 (SubmitPurchaseOrder) 执行它。

那么问题来了:在这种情况下,最佳实践是什么?

我的一些想法:

  1. UpdateOrInsertAddress 端点中的逻辑移动到控制器中的另一个方法,并从 UpdateOrInsertAddressSubmitPurchaseOrder 端点重用它。在这种情况下,我会将逻辑放入控制器中,但我不知道这是否正确。
  2. 创建另一个层,可能接近包含所有命令和查询的层,并在那里编写这种共享逻辑,稍后将由两个端点使用。
  3. 忘记重用,避免沉没成本谬误,只需创建一个新的 UpdateOrInsertAddress 命令,供两个端点使用。在这种情况下,该命令中将重复通过用户 id 检索地址、更新或插入的“逻辑”。

你遇到过这样的场景吗?最佳做法是什么?

1 个答案:

答案 0 :(得分:2)

嗯...首先你必须问自己是否会发生UpdateOrInsertAddress逻辑改变的情况,但你仍然想在SubmitPurchaseOrder中使用旧逻辑,换句话说:是UpdateOrInsertAddress 逻辑与 SubmitPurchaseOrder 紧密耦合,它应该总是在两个地方一起改变吗?


如果 UpdateOrInsertAddress 逻辑 ISSubmitPurchaseOrder 紧密耦合,那么不要使事情过于复杂并使用简单的重构技术,例如“提取方法”要重用代码(您的第一个想法对此很有效),只需将该方法设为私有以供内部使用。这并不意味着您将逻辑放入控制器中,您只是在重构,如果您担心,您甚至可以将这两个端点隔离在它们自己的控制器中,这样其他端点就不会看到共享代码。


如果 UpdateOrInsertAddress 逻辑 IS NOTSubmitPurchaseOrder 结合,那么复制代码(您的第三个想法)是一个非常明显的选择,因为即使视觉代码看起来相同,两个副本都有其存在的理由。复制条件时你必须小心,它们可能代表一些业务规则(你应该评估它),应该被提取到策略(例如:只有用户年龄 >= 18 可以注册等)并在共享代码之间重用,以保护您免受业务规则更改的影响。


与 CQRS 相比,您的问题更多地与常见的编程实践有关。

相关问题