I have recently came across this very interesting blog post by Jimmy Bogard ( the guy behind Mediatr, if you don’t know him). Talking about CQRS, he makes a good point about how the user should be informed of the result of a Command execution.
Should the Command Handler return a value?
Should the Command Handler throw an exception?
These are just some of the strategies we may take, another option could be just logging the operation and forget anything happened. Whatever.
A while ago I blogged about how to validate the Commands and ensure the data passed to the Command Handler is valid. This is the strategy I’m adopting in my projects lately. Why? Several reasons: first of all I want to keep Command execution separated from the validation, also Commands should be some sort of “fire and forget” operations. Let me clarify this a little bit.
In my opinion Command execution should be a boolean operation: the system can either execute it or not. Stop. I should be able to know ahead if a Command can be executed and that’s the validation phase. If I finally manage to get to the Handler, I know that the data I have is valid and I can run Command. No need to return a “true”.
So what should I do to make all the pieces fit?
- Use the Decorator pattern to ensure each Command Handler executes some sort of validation
- Analyze the Command and check its validity against business rules or anything else you want
- the Validator gives back a Validation result containing a (hopefully empty) list of errors
- in case something went wrong, throw a specialized Exception, for example something like this
Since most of the projects I am working on lately is composed of some sort of Web API based on .NET Core, I decided to create an Exception Filter that will eventually return to the user a JSON object with the details of the validation.
Some of you may have noticed that some of the links in this post point to this Github repository, LibCore. It’s a small set of utilities I am writing, mantaining and using in my projects. I thought it would be useful to share the sources, maybe just to hear comments from the community. Food for thought.