如果 CQS 阻止命令返回状态变量,那么如何为可能不成功的命令编写代码?假设您不能依赖异常。
似乎任何请求/响应都违反了 CQS。
所以看起来你会有一组“我可以妈妈”的方法来给出命令返回的状态。在多线程/多计算机应用程序中会发生什么?
如果我有三个客户端希望请求服务器的对象增加一(并且对象的限制为 0-100)。所有人都检查他们是否可以,但一个人得到了——而另外两个人不能,因为它刚刚达到了极限。看起来返回的状态可以解决这里的问题。
如果 CQS 阻止命令返回状态变量,那么如何为可能不成功的命令编写代码?假设您不能依赖异常。
似乎任何请求/响应都违反了 CQS。
所以看起来你会有一组“我可以妈妈”的方法来给出命令返回的状态。在多线程/多计算机应用程序中会发生什么?
如果我有三个客户端希望请求服务器的对象增加一(并且对象的限制为 0-100)。所有人都检查他们是否可以,但一个人得到了——而另外两个人不能,因为它刚刚达到了极限。看起来返回的状态可以解决这里的问题。
似乎任何请求/响应都违反了 CQS。
几乎是的,因此 Command-Query- Separation。正如 Martin Fowler所说:
基本思想是我们应该将对象的方法分为两个截然不同的类别:
查询:返回结果并且不改变系统的可观察状态(没有副作用)。
命令:更改系统状态但不返回值[我的重点]。
请求服务器的对象增加一个是Command,因此它不应该返回值 - 处理对该请求的响应意味着您正在同时执行 Command 和 Query 操作,这违反了 CQS 的基本原则。
因此,如果您想知道服务器的值是什么,请发出单独的Query。
如果你真的需要一个请求-响应模式,你要么需要一个复杂的回调事件过程来发出查询特定请求的状态,要么纯CQS 不适合你系统的这一部分——注意这个词纯。
多线程是 CQS 的一个主要缺点,并且可能很难做到。Wikipedia有一个基本示例和对此的讨论,还链接到同一篇 Martin Fowler 文章,他建议打破这种模式来完成某事而不会让自己发疯:
[Bertrand] Meyer [CQS 的发明者] 绝对喜欢使用命令-查询分离,但也有例外。弹出堆栈是修改状态的查询的一个很好的例子。Meyer 正确地说您可以避免使用这种方法,但它是一个有用的成语。所以我更愿意尽可能地遵循这个原则,但我准备打破它以获得我的流行。
TL; DR - 我可能只看返回一个响应,即使它不是正确的 CQS。
文章“种族条件不存在”可能会帮助您看待 CQS/CQRS 思维方式的问题。
您可能想退后一步,问为什么在发送命令之前绝对需要知道计数器值?显然,您想在客户端决定是否可以增加计数器。
方法是让服务器做出这样的决定。让所有客户端发送命令(有些会成功,有些会失败)。最终客户端将获得服务器对象状态的一致视图(已达到限制)并可能最终停止发送此类命令。
这个不一致的时间窗口会导致客户端做出错误的决定,但只要命令得到充分处理,它就不会破坏服务器端对象(或域模型)的一致性。