命令查询分离:命令必须返回void?

时间:2015-02-07 12:32:20

标签: command-query-separation

如果CQS阻止命令返回状态变量,那么命令的一个代码怎么可能不成功?假设你不能依赖例外。

似乎任何请求/响应都违反了CQS。

所以看起来你会有一套“母亲可能我”的方法给出了命令返回的状态。在多线程/多计算机应用程序中会发生什么?

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

2 个答案:

答案 0 :(得分:4)

  

似乎任何请求/响应都违反了CQS。

非常好,因此命令查询 - 分离 。正如Martin Fowler nicely puts it

  

基本思想是我们应该将对象的方法划分为两个截然不同的类别:

     

查询:返回结果,不要更改系统的可观察状态(没有副作用)。

     

命令:更改系统状态但不返回值 [我的重点]。

请求服务器的对象增加1是 Command ,因此它不应返回值 - 处理对该请求的响应意味着您正在同时执行命令和查询操作这打破了CQS的基本原则。

因此,如果您想知道服务器的价值是什么,请发出单独的查询

如果您确实需要请求 - 响应模式,则需要使用复杂的回调事件流程来发出对特定请求状态的查询,或者 pure CQS不合适对于你系统的这一部分 - 注意单词 pure


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

  [Bertrand] Meyer [CQS的发明者]绝对喜欢使用命令查询分离,但有   例外。弹出堆栈是修改查询的一个很好的例子   州。梅耶正确地说你可以避免使用这种方法,但是   这是一个有用的习语。所以我喜欢在可以的时候遵循这个原则,   但是我准备打破它以获得我的流行音乐。


TL; DR - 我可能只是看看返回一个回复,即使它不是正确的CQS。

答案 1 :(得分:2)

文章"Race Conditions Don’t Exist"可以帮助您查看CQS / CQRS思维模式的问题。

您可能想要退一步并询问为什么在发送命令之前必须知道计数器值?显然,您希望在客户端做出是否可以增加计数器的决定。

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

这个不一致的时间窗口会导致客户端做出错误的决定,但只要命令得到充分处理,它就永远不会破坏服务器端对象(或域模型)的一致性。