Arun Sasidharan

CommandQuery.jpg

Functions have side-effects. At times they change the state of the system when you least expect them to and wreak all kinds of havoc. It’s difficult to get rid of all side-effects in an Object Oriented programming paradigm. We just need to make sure to manage them so that they don’t bite us when we aren’t looking.

Managing Side Effects

One of the good ways to manage side-effects is to create a strong separation between commands and queries. In this context, a command changes the system, it has a side effect. A query returns the value of a computation or the observable state of the system.

Example

When you call a function getAmount() , you expect it to just return the amount and not change state of the system. It would be horrific if it did. Similarly, when you call setAmount() , it will have side-effects and you expect it to change the state of the system. But what do you expect setAmount() to return? Probably nothing.

Formal Definition

Command Query Separation formalises this by saying:

"Functions that change state should not return values and functions that return  values should not change state.

This term was coined by Bertrand Meyer in his book Object Oriented Software Construction.

Advantages

One of the advantages of following this separation is that you can easily recognize whether or not a function has a side-effect.

int m();  // query
void n(); // command

Violation

Take a look at the call below. Is it a command or a query? Clearly, it changes the state of the system.

User u = UserService.login(username, password);

What about the user object? Why was it returned? Are you supposed to manage it? Why did the login function return the user? Shouldn’t it rather be a simple getter?

User u = UserService.getUser();

Error Handling

Maybe login() returned the User so it could return null when it failed? We are tempted to return error codes from a command if it fails to change state. But it’s better to throw an exception, maintaining the convention that commands return void.

Gotchas

Though CQS works well most of the times, but there are exceptions. Popping a stack is an example of a function that modifies state and returns a result like a query.

Element e = Stack<Element>.pop(); // stateful query

Summary

So in short, commands return void and queries return values. Use exceptions rather than returning and checking for error states.

As Martin Fowler says, it would be nice if the language itself would support this notion. The language could detect state changing methods, or at least allow the programmer to mark them. But we are yet to see a language or an IDE that supports such markings.

Please be in touch if you have any questions


Arun Sasidharan Arun Sasidharan Senior Android Engineer at Fueled

Arun is a Senior Android Engineer at Fueled and eats software for breakfast. The best way to reach him is on his Twitter account https://twitter.com/_arunsasi

Related Search Term(s): Tutorials

Create, Design, Develop and Connect at AnDevCon D.C. 2017!

Thoughts? Leave a comment: