Command and Command Handlers (and Why I Donāt Care Much For Them)
Introduction
I want to complain about the pattern of using Commands and Command Handlers in this article, but I donāt want to spend my time explaining what they are, so Iāll link you to another blog post. Itās pretty in-depth, so it may take a bit, but what I really like about it is that itās part of a collection of posts related to the book, Architecture Patterns with Python: Enabling Test-Driven Development, Domain-Driven Design, and Event-Driven Microservices. From what Iāve read in it so far, itās a lot like the book I was about to write, but a little less in-depth on the product theyāre building throughout and also not covering some of the more obscure practices. Iām greatly enjoying it so far, despite largely knowing it all already, so Iām here to plug it. You can purchase it, or you can read it for free on their web site.
So, now Iām probably not going to write that book. Iāll likely still make a series of tutorials or something that I can monetize that tie together in a similar way. But since the majority of it is already covered, I can skim through those topics and link back to their book to save some effort.
Pros of the Pattern
Anyway, moving on. So, why donāt I like the Command Handler pattern? In short, itās because itās an abstraction of a function that gives very little benefit. Iāll list the benefits first, so that it doesnāt look like Iām being unfair.
- Itās quite abstract. I technically already said this, but Iām reiterating it. Being more abstract means that it allows for a reusability and repeatability.
- Itās a fairly simple and well-known pattern, making it relatively easy to pick up on for new people on the project.
- Itās easy to organize. You can place all of your Commands (and maybe handlers, too) in one area and that shows to new people what use cases are available. If you place the handlers in the same or similar location, it makes it easy to see which handlers have already been handled and how theyāre implemented.
- Because itās so big and obvious, it helps force you into a good pattern. A lot of other patterns are too easy to ignore, leading to going of in a different direction and making spaghetti code.
Cons of the Pattern
So, with all these benefits, what could I possibly have against it?
The primary reason is that itās overengineered, in my opinion. You only need one part of the pattern (the handlers) to largely accomplish all of the above. Itās slightly less effective at it, but I feel like the trade-off actually provides more clarity and makes it easier to grok the codebase.
Before moving on to what I think is generally a better idea, Iāll give you another reason why Iām not a fan: itās too dynamic. You dynamically register Commands with their Handlers on the Queue. If you donāt register the Commands and Handlers, you can have all the other building blocks in place and it could still fail. And because itās a dynamic registration, even a type-aware compiler canāt help you know that you donāt have everything in place. This means that itās possible to write a web router that adds the proper Command onto the Queue and have a proper Command Handler written for that Command, but it still wonāt run. Presumably, you have something written for the Queue to alert you when a Command type isnāt registered when one comes through, but thatās a runtime solution. This is the same problem I have with dependency injection frameworks.
Along with that, itās an extra step at runtime, checking the type of the Command and looking up the Handler instead of just calling the Handler directly. Itās even possible to accidentally register them incorrectly and, in a dynamic language, have nothing to ensure that it would even work.
What Do I Suggest Instead?
So whatās my alternative? Well, it largely already exists in the as the basic service layer in DDD. The service layer provides you with all the actions youāre allowed to use on the domain. Instead of creating the Commands and Command Handlers that (often) simply redirect to the service layer functions, just break all those service layer functions into their own Action objects. Thatās not an official term; Iām just going to refer to them that way for the rest of the post.
These Action objects encapsulate both the Commands and Command Handlers into single objects. By doing so, at a minimum, you can at least stop naming everything FooCommand and FooHandler. You just name it the āFooā part. If you really want, you can add a āCommandā (which could be confused with the other pattern), āActionā (which is kind of superfluous), or āServiceā (possibly the best option, though it will tend to lead people away from the best naming pattern for the āFooā part) suffix, but I suggest against that.
Anyway, Actions can take in the dependencies that the Command Handler uses via a constructor, and has a function (or IS a function, if that function is __call__(...)) that takes all the necessary information as parameters instead of a Command object (which incidentally, is really just an abstraction of a parameter list).
What about the Command Queue? It has extra scalability benefits, made possible by the Command pattern, right? Sure, the Command pattern makes the Queue pretty simple to build, but itās still actually possible to use a queue with Actions. And with Actions, you donāt need to register anything. Youāre effectively just adding functions to the queue that can be run later. You just need to have a way to give it all the parameters without running right away. A functools.partial can take care of that, or some other kind of function that will run the Action later. You could even add another method to the Action type that does that for you. For example, in Python:
class MyActionType:
def __init__(self, dependency1, dependency2):
self.dep1 = dependency1
self.dep2 = dependency2
def do_action(self, param1, param2):
...
def prepare_action(self, param1, param2):
def prepped_action():
return self.do_action(param1, param2)
return prepped_actionHere, the Action type provides a prepare_action method that will return a function that takes no arguments and will call the main Action method. That returned function can be added to the queue, and the queue can just call it when it comes up.
Disclaimer
Despite all of this, I still think thereās a place for the Command pattern. Itās primary benefit is in a big, distributed system, I think. Plus, I donāt have any solid experience with either pattern, so you can definitely take my opinion with a grain of salt (though it IS pretty much the same pattern as suggested by some other smarter, more experienced people in a conference talk that I sadly canāt find right now). The Command pattern definitely does a better job of preventing spaghetti code, but it only takes a little extra discipline to stick with the Actions pattern properly.
Outro
So there you have it, my simpler replacement for the command pattern. I didnāt think Iād actually write this much if I didnāt explain the Command pattern. Now Iām REALLY glad I didnāt bother to describe it! Do with this pattern what you will; I just needed to get all of this off my chest.
Clarification Update:
I want to make something clear: My opinion of Commands and Command Handlers is not the same opinion of Events and Event Handlers. At a surface level, theyāre almost exactly the same, but they do have one major difference that makes them far more worthwhile, and itās not semantics. You can have multiple Handlers run for the same Event (or none!). And you can even have the same Handler registered for multiple Events! If you were to do the same with Commands, then youāre breaking the understanding of them.
A Command is ādo this one thingā. Once youāve done the thing, that thing can become an Event that can trigger other things to happen, but if there are multiple things that need to happen directly because of a Command, those are details that the Command abstracts over within a single Handler. And if certain things have to happen after others, the first thing can create an Event that the follower actions can subscribe to. And if your Event system runs multiple handlers in parallel, you could even potentially run multiple follower actions at the same time that all only depend on a previous action, which is an easier way to parallelize than to do it directly in the Command Handler.
Abstractly, Events donāt always have to have subscribers, either! Business logic may demand that certain handlers always be ready, but thatās specific to certain Events, not to the idea of Events. For example, a secondary system may subscribe when it is available, and after itās satisfied, it can unsubscribe. If nothing is subscribed to a Command in order to carry it out, is it really a Command?
Plus, thereās that whole naming thing again. With Commands, you name one half āDoThisCommandā and the other half āDoThisHandlerā. With my Action system, you have a single type or function just called āDoThisā. With Events, you have Events either named āThisHappenedEventā or even just āThisHappenedā, and the Event Handlers are named after what they do. Because there can be multiple, you donāt WANT to name them āThisHappenedHandlerā.
Carried out to their full potential, every function call could effectively be done via Commands, Events, and their Handlers. There is a point where youāre taking it too far, and I believe that most of the time the Command pattern isnāt that useful, but the Event one is.
Published on Java Code Geeks with permission by Jacob Zimmerman, partner at our JCG program. See the original article here: Command and Command Handlers (and Why I Donāt Care Much For Them) Opinions expressed by Java Code Geeks contributors are their own. |



Hi, I agree with you.
Command pattern is abused in a lot of architectures nowadays.
The only where I used it with success it was a CAD application with an “important” user interface. Having all operations represented by Command simplified the management of undo/redo.
Thanks again.
Regards
R