8

If CQS prevents commands from returning status variables, how does one code for commands that may not succeed? Let's say you can't rely on exceptions.

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

So it would seem like you would have a set of "mother may I" methods giving the statuses that would have been returned by the command. What happens in a multithreaded / multi computer application?

If I have three clients looking to request that a server's object increase by one (and the object has limits 0-100). All check to see if they can but one gets it - and the other two can't because it just hit a limit. It would seem like a returned status would solve the problem here.

Dave Schweisguth
  • 36,475
  • 10
  • 98
  • 121
MKaras
  • 2,063
  • 2
  • 20
  • 35

2 Answers2

6

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

Pretty much yes, hence Command-Query-Separation. As Martin Fowler 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].

Requesting that a server's object increase by one is a Command, so it should not return a value - processing a response to that request means that you are doing a Command and Query action at the same time which breaks the fundamental tenet of CQS.

So if you want to know what the server's value is, you issue a separate Query.

If you really need a request-response pattern, you either need to have something like a convoluted callback event process to issue queries for the status of a specific request, or pure CQS isn't appropriate for this part of your system - note the word pure.


Multithreading is a main drawback of CQS and can make it can hard to do. Wikipedia has a basic example and discussion of this and also links to the same Martin Fowler article where he suggests it is OK to break the pattern to get something done without driving yourself crazy:

[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 - I would probably just look at returning a response, even tho it isn't correct CQS.

Community
  • 1
  • 1
Rhumborl
  • 16,349
  • 4
  • 39
  • 45
3

Article "Race Conditions Don’t Exist" may help you to look at the problem with CQS/CQRS mindset.

You may want to step back and ask why counter value is absolutely necessary to know before sending a command? Apparently, you want to make decision on the client side whether you can increase counter more or not.

The approach is to let the server make such decision. Let all the clients send commands (some will succeed and some will fail). Eventually clients will get consistent view of the server object state (where limit has reached) and may finally stop sending such commands.

This time window of inconsistency leads to wrong decisions by the clients, but it never breaks consistency of the object (or domain model) on the server side as long as commands are handled adequately.

uvsmtid
  • 4,187
  • 4
  • 38
  • 64