The Power Of Commands And Events 🔊

Every state change starts with an order

The design artwork from the Magic card called Saskia the Unyielding. The picture shows a woman with tribal tattoos wearing a leather armor. She's pointing her finger somewhere, screaming. In the background, an army of men run towards the direction the woman is pointing to, following her command.

A computer program represents the collection of many subsystems. A single subsystem has little value on its own, for that the value is only delivered when all the subsystems work together in unison to produce something useful.

Note: To have a better idea of what that means, watch this talk.

Each of those interactions can be considered messages triggered by one subsystem and listened by another one. When that message represents an order, you call it a “command.”

When you open a door, you execute a command. The command starts in your brain until it's received by the parts of the body responsible to execute it.

The command can also start from somebody else's order. You listen to the order and then it triggers a decision in your brain to either follow it or not.

A command happens when a Client sends a message to a Server and that message represents an order

The term Client can be used to describe a subsystem that knows which command to send; the term Server can be used to describe a subsystem that knows how to execute the command.

To understand what is Client and what is a Server you need to specify the context you’re looking at.

The pseudo-code representing the conceptual model of a Human opening the door. There's a comment called "Initialization." Below the comment, there's a code to instantiate a "Human" object and a "Door" object. In the bottom, the "Human" instance calls a method named "open" which passes the "Door" instance as the argument.

In the example above, the Initialization comment is a hidden subsystem that is not modeled like the Human and the Door. That subsystem is responsible for sending a message to the Human representing the command to open the Door. In this context, the Initialization is the Client; the Human and the Door are the Servers.

When the Human subsystem receives the message to "open the door", it will trigger a series of low-level commands to the Brain. In this context, the Human is the Client; the Brain is the Server.

Any method or function call is a command, as long as it has the intention to change the state of the Server

When the browser sends a POST, PUT or DELETE request into a web server using the HTTP protocol, it's also sending a command.

In this case, the Client will be the HTML code which sends the POST command using a form submission, or the JavaScript code which sends the command using an AJAX request.

The Server will be the code on the other side of the network, created to understand the HTTP protocol and handle the commands accordingly.

The code for an HTML and a JavaScript client that makes a request to a server hosted on "example.com." The HTML client is a form that can afford the user to submit a "username" via POST request. The JavaScript client is a "fetch" API that executes the same request inside a function called "submit username."

In the code above, the "submit username" function and the HTML form represent the Client. The code for the HTTP Server hosted on "example.com" represents the Server.

In the context of HTTP, the methods POST, PUT and DELETE are commands

When you use the Command-Line Interface, you send commands to instruct the program to do something.

In that case, the Client is the person who types the command. The Server is the program that does something with it.

The code showing the example of a basic use of Git. In the first line, there's a "git commit" command with the message "Separate the installation docs in sections." In the second line, there's a "push" command which uploads the "master" branch to the default remote repository labeled as "origin."

In the example above, the Client is the programmer; the Server is the git C.L.I.

In the context of a Command-Line Interface, the Client is the person who sends the commands. The Server is the program that handles it.

Every time a command is executed, it creates an event. The event is always there, even if you don’t model it in the code:

  • After you open the door, the "door is opened."
  • After you submit the user details, the "user is created."
  • After you commit the code, the "code is committed."

There's a huge difference between commands and events.

While a command can be interrupted — say due to a validation failure — an event cannot. An event represents the model for the side-effect of something that already happened.

It's immutable. It never changes.

The only way to get another event is to try to execute the command again.

  • When you try to open the door, the door is locked. When you try to open the door with the key, the "door is opened."
  • When you try to submit the user details, the server is offline. When you try to submit the username when the server goes back online, the "user is created."
  • When you try to commit the code using Git, the commit fails because the working tree is dirty. When you add the changes to the index and try to commit the code again, the "code is committed."
An event is immutable and always named in the past because it represents something that already happened.

Ok, but what’s the point of all this?

I have mentioned in a previous post that due to how we express thoughts, it is possible that in a real conversation two individuals believe they are talking about the same “thing”, but in reality, they are talking about things that are completely different.

When talking about complex concepts, the subjective interpretation of each interlocutor is the one that will drive the quality of the discussion.

Somebody can talk about the "door open" concept inside a program. However, that doesn’t clearly express what’s the cause and what’s the effect of the internal interactions. Given a computer program is the product of the interaction of its parts, the cause and effect are very important to communicate the purpose of the program.

When you write code, you can separate cause and effect clearly. You do that by modeling your subsystems in a way that commands and events are separated from each other.

For example, the command "hi server, start!" creates the event "server started."

The code showing the call for a method named "start" from a "server" variable. In the second line, there's an event handler for the "server started" event created from that command containing a code comment saying "Do something after the event happened".
In the context of the communication between two or more subsystems, a Command is a conceptual representation for when a Client sends an authoritative message with the intent to change the state of a Server.

You can find numerous examples of commands and events in Software Development.

  • A method or function call with the intent to change the state of another object is considered a command.
  • An HTTP request submitted with the intent to change the state of a website, such as POST, PUT or DELETE is also considered a command.

Events are not the same. They represent something that happened in the past.

  • After you execute the command to "open the door", the "door is opened."
  • After you execute the command to "commit the code", the “code is committed.”

Commands and events are fundamentals.

They are everywhere.

However, they’re not always identified as such and may require a little bit of effort to be seen.

Once discovered, they'll allow a program to represent clearly how subsystems communicate and the side-effects of that communication.

It will make the code more legible, self-documented and allow you to have more control of it.

If you do this, there’s only one event that will ever happen after somebody looks at the code you write:

"it made sense."


Thanks for reading. If you have some feedback, reach out to me on Twitter, Facebook or Github.