Commands and Queries

Written by Enrique Comba Riepenhausen on 13/12/2024
Photo used in this post by wd toro 🇲🇨 on Unsplash

A general is just as good or just as bad as the troops under his command make him.

~ Douglas McArthur

We are currently working on a project to protect vulnerable people from phishing attempts. The project itself will be released in the beginning of next year while we are preparing our last touches to it (and to be honest enjoying our holidays too).

We decided to code it using the latest version of Ruby on Rails. Rails has grown so much as a framework from when I started using it back in the early 2000s. I’m really impressed by what the team has archived with this new version (it’s never been simpler to write and realease software when you have a small saas business).

As we were writing our code we didn’t realy like how we were adding functionality to the controllers and the awkwardness of writing tests for the controllers themselves (I much rather have some higher level tests that make sure a feature works using something like cucumber or cabybara).

There are many approaches to organise your code; Rails projects are known for creating a Service object and put all the business logic into a Service classes. The prolem I have with the service concept is that it usually muddles the waters a little bit and you either end up with a lot of small services (not that bad) or a bunch of really big service classes (not adivsable).

In order to write sustainable code I prefer to write classes that are small and do one thing only; I much rather have more smaller classes that meaninfully reveal intent, than big balls of mud that do to much.

Command Query Separation

One approach to clean up your codebase is using Command Query Separation. In a nutshell this means you separate your application logic (or business logic) into commands and queries.

When you want some data you’ll be issuing a query and when you want to modify data you’ll issue a command; it’s pretty straight forward.

The beauty of this comes into play when you are working on the project; because of this separation, you always know where to look for the code (either in the commands or queries subdirectories/modules).

In our implementaion Commands and Queries are very similar in structure even though they do different things conceptually.

Let’s see a command in action:

1
Command::GuestOrSubscriber.with(email_address: incoming_mail.from)

The command itself looks something like this:

1
module Command
2
class GuestOrSubscriber
3
include Command
4
5
def execute
6
::User.find_or_create_by(subject)
7
end
8
end
9
end

This particular command uses the User model and the ActiveRecord method find_or_create_by to either find and existing user or creating a new “guest” user. If you are a purist you’d (not wrongly) argue that a Command should not have any return values. Normally I would agree with you, but we chose not to add more complicated infrastructure to the project (like event queues, etc.) and instead play along with what Rails has to offer.

The included Command module is fairly straight forward – when included you will only have to implement the execute method (which has access to the subject – the arguments passed in the with class method).

Queries are similar to Commands (they share some of the code), but instead of an execute method you have to implement an answer method. The resulting code looks like something like this:

1
module Query
2
class User
3
include Query
4
5
def answer
6
::User.find_by(subject)
7
end
8
end
9
end

There are cases where we wanted to change the calling method to the commands and queries to make the code more readable.

An example of this would be when we are checking if a user is allowed to perform some action:

1
Query::UseService.permitted(user)

The way we do this is by adding this simple line of code inside the UserService query:

1
class << self
2
alias_method :permitted, :in
3
end

By separating our code in command and queries we create highly readable code that at the same time is easy to find in a growing codebase.

Building a command and queries infrastructure inside your Rails application is fairly simple (we considered releasing this as a gem so you can add it to your rails project, but haven’t gotten to it yet).

How do you organise the code inside your applications? I’d love to hear from you!

back to the blog