命令查询分离:命令必须 return 无效?

Command Query Separation: commands must return void?

如果CQS 阻止命令返回状态变量,那么对于可能不成功的命令如何编写代码?假设您不能依赖异常。

似乎任何 request/response 都违反了 CQS。

所以看起来您会有一组 "mother may I" 方法来提供命令返回的状态。多线程/多计算机应用程序中会发生什么?

如果我有三个客户端希望请求服务器的对象增加一个(对象的限制为 0-100)。所有人都检查他们是否可以,但一个得到它 - 而另外两个不能因为它刚刚达到极限。返回状态似乎可以解决这里的问题。

It seems like anything that is request/response is a violation of CQS.

几乎是,因此命令查询-分离。正如马丁·福勒 nicely puts it:

The fundamental idea is that we should divide an object's methods into two sharply separated categories:

Queries: Return a result and do not change the observable state of the system (are free of side effects).

Commands: Change the state of a system but do not return a value [my emphasis].

请求服务器的对象增加 1 是一个 命令,所以它不应该 return 一个值 - 处理对该请求的响应意味着你正在做同时执行命令和查询操作,这违反了 CQS 的基本原则。

所以如果你想知道服务器的值是什么,你发出一个单独的查询

如果你真的需要一个请求-响应模式,你要么需要像复杂的回调事件过程这样的东西来查询特定请求的状态,要么 pure CQS 不适合您系统的这一部分 - 请注意 pure.

这个词

多线程是 CQS 的一个主要缺点,它很难做到。 Wikipedia 有一个基本示例和对此的讨论,还链接到同一篇 Martin Fowler 文章,他在文章中建议可以打破模式来完成某些事情而不会让自己发疯:

[Bertrand] Meyer [the inventor of CQS] likes to use command-query separation absolutely, but there are exceptions. Popping a stack is a good example of a query that modifies state. Meyer correctly says that you can avoid having this method, but it is a useful idiom. So I prefer to follow this principle when I can, but I'm prepared to break it to get my pop.


TL;DR - 我可能只会查看 return 的回复,即使它不是正确的 CQS。

文章"Race Conditions Don’t Exist"可能会帮助你用CQS/CQRS的心态看问题。

您可能想退一步问为什么在发送命令之前绝对有必要知道计数器值?显然,您想在客户端决定是否可以增加计数器。

方法是让服务器做这样的决定。让所有客户端发送命令(有的会成功,有的会失败)。 最终 客户端将获得服务器对象状态(已达到限制)的一致视图,并可能最终停止发送此类命令。

这次 window 的不一致导致客户端做出错误的决定,但只要命令处理得当,它就不会破坏服务器端对象(或域模型)的一致性。