In wikipedia's definition of command query separation, it is stated that
More formally, methods should return a value only if they are referentially transparent and hence possess no side effects.
If I am issuing a command, how should I determine or report whether that command was successful, since by this definition the function cannot return data?
For example:
string result = _storeService.PurchaseItem(buyer, item);
This call has both a command and query in it, but the query portion is result of the command. I guess I could refactor this using the command pattern, like so:
PurchaseOrder order = CreateNewOrder(buyer, item);
_storeService.PerformPurchase(order);
string result = order.Result;
But this seems like it's increasing the size and complexity of the code, which is not a very positive direction to refactor towards.
Can someone give me a better way to achieve command-query separation when you need the result of an operation?
Am I missing something here?
Thanks!
Notes: Martin Fowler has this to say about the limits of cqs CommandQuerySeparation:
Meyer likes to use command-query separation absolutely, but there are exceptions. Popping a stack is a good example of a modifier 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.
From his view, it's almost always worth it to refactor towards command/query separation, except for a few minor simple exceptions.
These links may help
Take some more time to think about WHY you want Command Query Separation.
"It lets you use queries at will without any worry of changing system state."
So it is OKAY to return a value from a command to let the caller know it succeeded
because it would be wasteful to create a separate query for the sole purpose of
finding out if a previous command worked properly. Something like this is okay in
my books:
A disadvantage of your example is that it is not obvious what is returned by your
method.
It is not clear what 'result' is exactly.
Using CQS (Command Query Seperation) allows you to make things more obvious
similar to below:
Yes, this is more code, but it is more clear what is happening.
I see a lot of confusion above between CQS & CQRS (as Mark Rogers noticed at one answer as well).
CQRS is an architectural approach in DDD where, in case of a query, you do not build up full blown object graphs from aggregate roots with all their entities and value types, but just lightweight view objects to show in a list.
CQS is a good programming principle on code level in any part of your application. Not just the domain area. The principle exists way longer than DDD (and CQRS). It says not to mess up commands that change any state of the application with queries that just return data and can be invoked any time without changing any state. In my old days with Delphi, the lanquage showed a difference between functions and procedures. It was considered a bad practice to code 'functionprocedures' as we called them back than as well.
To answer the question asked: One could think of a way to work around executing a command and getting back a result. For instance by providing a command object (command pattern) which has a void execute method and a readonly command result property.
But what is the main reason to adhere to CQS? Keep code readable and reusable without the need to look at implementation details. Your code should be trustworthy not to cause unexpected side effects. So if the command wants to return a result, and the funcion name or return object clearly indicates that it is a command with a command result, I'll accept the exception to the CQS rule. No need to make things more complex. I agree with Martin Fowler (mentioned above) here.
By the way: wouldn't strictly following this rule break the whole fluent api principle?
I like the event driven architecture suggestions other people have given, but I just want to throw in another point of view. Maybe you need to look at why you're actually returning data from your command. Do you actually need the result out of it, or could you get away with throwing an exception if it fails?
I'm not saying this as a universal solution, but switching to a stronger "exception on failure" instead of "send back a response" model helped me a lot in making the separation actually work in my own code. Of course, then you end up having to write a lot more exception handlers, so it's a trade off... But it's at least another angle to consider.
The question being; How do you apply CQS when you need the result of a command?
The answer is: You don't. If you want to run a command and get back a result, you aren't using CQS.
However, black and white dogmatic purity could be the death of the universe. There are always edge cases and grey areas. The problem is that you begin to create patterns that are a form of CQS, but no longer pure CQS.
A Monad is a possibility. Instead of your Command returning void, you could return Monad. a "void" Monad might look like this:
Now you can have a "Command" method like so:
The problem with grey area is that it is easily abused. Putting return information such as the new OrderID in the Monad would allow consumers to say, "Forget waiting for the Event, we've got the ID right here!!!" Also, not all Commands would require a Monad. You really should check the structure of your application to ensure you have truly reached an edge case.
With a Monad, now your command consumption might look like this:
In a codebase far far away . . .
In a GUI far far away . . .
Now you have all of the functionality and properness you want with just a bit of grey area for the Monad, but BEING SURE that you aren't accidentally exposing a bad pattern through the Monad, so you limit what you can do with it.
Well, this is a pretty old question but I post this just for the record. Whenever you use an event, you can instead use a delegate. Use events if you have many interested parties, otherwise use a delegate in a callback style:
you can also have a block for the case where the operation failed
This decrease the cyclomatic complexity on the client code
Hope this helps any lost soul out there...