CommandBus and CQ(R)S are gaining a lot of popularity over last year. Today I got question about benefits of the switch. As I used it by default for last year I’ve never thought about it. I’ll try summarize it in this article and in next one I’ll explain how you can change your architecture in life project in reasonable and production safe way. Let’s get to it!
Why should you use CommandBus
CQS stands for Command Query Separation. Simple as it is – every operation which is not just read in encapsulated in Command and handled by CommandHandler. The biggest benefit of that approach is that you have each business operation in separate class. Thanks to that when change has to be made it’s very clear where it should be done and when new feature comes in it won’t interfere with what you already have.
Second argument is very close with first and it’s about communication between dev team and business. Each handler is one specific case and it’s name reflects business language more than what dev team thinks it is. You’re dropping meaningless .*Service classes which grows out of reasonable size very fast.
Stopping unreasonable growth is part of Solid. Single responsibility principle says that each class should have specific functionality. Keeping separate handlers is the best way for that.
Very important in all of that is separation between input and business logic. All you can do outside CommandBus is to create and validate command and send it through with bus. Your controllers are getting very thin and probably you can do half of the things automatically even before it. You also stopping to care where and how command is created. You can execute the same operation from many places without any modifications in your business code.
Cherry on top when you’re creating any API is that you can deserialize your input whatever it is (JSON/XML) straight to object of the command. It saves a lot of time, especially with Symfony 2 where you can create very neat ParamConverter to do the thing for you and throw 400 if validation fails.
Let’s take UserService from thin controller fat service architecture. You have there two methods – registerUser and updateUser. First one creates user and sends confirmation email. Second just updates fields in User.
First thing broken is SOLID as two operations are handled by the same class. You also have to have dependency on some mailer to be able to send email during registration. But do you need to instantiate it when updating user? No. So we can assume you’re looting time and resources on every update of the user.
Question also is – WTF is “updateUser” – which business process is it? When user changes email? When user changes password? When user is promoted to different role?
Usually all from above processes will use this method and you will have lovely stack of ifs to determine when you have to send confirmation of new email, encode password or just update column with role value. Or even worse you’ll have event listeners on specific fields hidden somewhere deep in code and first new person will add another one because of no knowledge of old ones and after another month you will be adding parameters to enforce listeners to be fired in proper order.
Been there done that ;)
With each process in different class you’re avoiding all of that. You’re doing your tasks with speed and precision saving your time and business money.