8

我一直在研究 CQRS,但我发现它在显示命令结果时会受到限制,比如说 Web 应用程序。

在我看来,使用 CQRS,一个人被迫刷新整个视图或部分视图以查看更改(使用第二个请求),因为原始命令请求将仅存储要在将来处理的事件。

在 Web 应用程序中,命令请求是否有可能将它创建的事件的结果传送回浏览器?

4

2 回答 2

5

这个问题的标题的答案很简单:什么都没有,空的或从 webbrower/rest 的角度来看 200 OK 和空的身体。

应用于系统的命令(如果成功提交更改)不会产生结果。如果您希望将业务逻辑留在服务器端,是的,您确实需要通过对服务器执行另一个请求(查询)来刷新数据。

但是,大多数情况下,您可以摆脱到服务器的第二次往返。取一张表格,在其中修改一行,然后按保存按钮。你真的需要更新表格吗?或者,如果用户在博客文章上提交评论,只需将评论附加到 dom 中的其他评论,而无需往返。

如果您发现自己想要从服务器返回修改后的状态,则需要认真考虑您要实现的目标。大多数情况都可以更改,因此简单的 200 OK 就足够了。

更新:关于您关于排队传入命令的问题。不建议将传入命令排队,因为这可能会返回误报(命令已成功接收并排队,但当命令尝试修改系统状态时它会失败)。该规则有一个例外,那就是如果您的系统具有仅附加模型作为状态。如果命令有效,那么将系统状态的突变排队到稍后是安全的。

Udi Dahans 名为 Clarified CQRS 的文章始终是有关此主题的好读物http://www.udidahan.com/2009/12/09/clarified-cqrs/

于 2011-01-01T11:34:57.607 回答
0

考虑到命令可以被接受或拒绝,异步命令在 CQRS 中是一件奇怪的事情。我写过它,在我的博客上提到了 Udi Dahan 的愿景和 Greg Young 的愿景之间的争论:https ://www.sunnyatticsoftware.com/blog/asynchronous-commands-are-dangerous

回答您的问题,如果您努力以事务方式设计域对象(聚合?),其中每个命令都会启动一个以零、一个或多个事件结尾的事务(独立于稍后是否有一些流程管理器,选择一个事件并启动另一个事务),那么我认为没有理由有一个空的命令结果。对于启动用例的外部参与者来说,接收一个命令结果非常有用,该结果表明命令是否被接受,它产生了哪些事件,或者现在哪个特定状态具有域(例如:聚合版本)。

当您使用异步命令在 CQRS 中设计一个系统时,期望命令会成功并且您会收到通知的快速状态更改是错误的。

有时,域需要根据这些服务 api 以异步方式与外部服务(域服务?)进行通信。这并不意味着域不能产生有意义的域事件,以同步方式通知正在发生的事情以及域中发生了哪些变化。例如,以下流程很有意义:

  1. Actor 发送同步命令 PurchaseBasket
  2. Domain 使用 MakePayment 的外部服务并知道正在处理付款
  3. 域产生事件 BasketPurchaseAttempted 和/或 PaymentRequested 或类似事件
  4. 尽管如此,该命令仍会同步返回结果 200 Ok,其中包含指示有关已发生事件的一些信息的有效负载。即使支付没有完成,因为支付平台是异步的,至少参与者对它发起的交易的结果有一个有意义的了解。

将此设计与异步设计进行比较

  1. Actor 发送异步命令 PurchaseBasket
  2. 系统返回 202 Accepted 并带有交易 ID 表示“感谢您的关注,我们会打电话给您,这是票号”)
  3. 在单独的流程中,域向支付平台发起流程管理器或类似的流程,当流程完成时(如果完成,假设命令被接受并且没有禁止购物篮的业务规则),那么系统可以开始通知参与者的过程。

考虑如何测试这两种情况。考虑如何设计用户体验来适应这一点。你会在 UI 的第二个场景中显示什么?你会假设命令被接受了吗?您是否会在显示交易 ID 时显示感谢信息和“请稍候”?您是否愿意大步向前,让用户在加载屏幕上等待异步进程完成并通过 Web 套接字或轮询策略通知 XXX 秒?

CQRS 中的异步命令是一件危险的事情,让我们懒惰的域设计者。

于 2020-11-12T08:59:02.763 回答