When to validate commands in CQRS?



I’m continuing the series about CQRS to supplement my recent CQRS in Practice course. There’s a question that I didn’t cover in the course and that was raised at least twice since then: when to validate commands in CQRS?

CQRS commands, command handlers, and validation

In a typical CQRS application with a single database, the write side looks like this:

When to validate commands in CQRS: CQRS write side

CQRS write side

  • The client sends a request to the API (the server). The request contains data that is represented by a DTO (data contract).
  • The server routes the request to a controller which then transforms the incoming DTO into a command and dispatches it to a command handler.
  • The command handler is where the application logic resides. It retrieves necessary data from the database, delegates decision-making to domain classes, and persists the results of those decisions back to the database.
  • Finally, the client receives an acknowledgment: an indication of either success or failure.

So, where in this picture does validation lies? When exactly should you validate a command before acting upon it?

When it comes to preliminary validation, such as checking for non-nullability and such, you could put precondition checks into commands themselves:

This could help avoid transmitting invalid commands to command handlers and follow the fail fast principle. You can even introduce a static factory method returning a Result instance, similar to Value Objects:

Would it be a good idea?

To answer this question, we need to revisit what a command is. A command is a message that tells your application to do something. The application can either accept or reject this message, depending on the application’s current state. There’s no guarantee that the application will go ahead and execute the command.

This is one of the differentiating factors between commands and events. Unlike a command, a domain event represents a fact that already happened and the application can’t do anything about it. It can either take it into account or ignore, but not change or reject it.

Because a command represents things the client asks of your application, that could be anything, including something invalid. Therefore, commands shouldn’t have any invariants attached to them. The application, in turn, is free to reject an invalid command. It means that a command should be a plain bag of properties with no validations:

So where to do the validation then? There are a couple of options: either before dispatching the command (in the controller) or after (in the command handler).

Ideally, all validations should be done after the command dispatch. You want to keep the controller as thin as possible – it should only be responsible for the built-in ASP.NET functionality (such as routing) and converting DTOs into commands. Everything else should go to the domain model or commands handlers. This will help you keep a good separation between ASP.NET-related and application-related concerns.

Even trivial validations, such as checking for nulls, field lengths and so on, should go to the domain model in an ideal case. That’s because the information regarding what constitutes a valid email, course name, or student address is part of the domain knowledge and should be kept in the core domain layer (preferably in value objects).

The drawback of this approach is that it’s quite daunting, especially in projects without much complexity. In such simple projects, it may be an overkill to create value objects for each concept in the domain model, such as Email, CourseName and so on. (Check out this article to decide when to create a value objects: Value Objects: when to create one? )

The simpler approach is to rely on the built-in validation mechanism, such as ASP.NET attributes, or tools like FluentValidator. In such a scenario, you will validate commands before they get to command handlers. Which is not ideal from a pureness perspective, but is fine overall if you think that the simplicity gain is worth it. I wrote about a similar topic in this article: Validation and DDD .

Note two things:

  • Even if you take the simpler approach (attributes over value objects), complex validations (such as checking for student’s email uniqueness) should still be done in the command handlers.
  • And if you have an HTML client, you will still need to duplicate the validations on the UI, at least the simple ones, for better user experience. No one wants to wait for a server roundtrip just to see that the email they entered is invalid.

Summary

  • Commands should have no invariants attached to them. The server is free to reject an invalid command.
  • Ideally, all validations should reside either in command handlers or in the domain model. The drawback of this approach is its complexity.
  • In simpler projects, use attributes to streamline the validation. This approach is not as pure, but it’s simpler.

Other articles in the series

Share




  • http://www.kamilgrzybek.com Kamil Grzybek

    Vladimir, great article again!

    What a coincidence that I wrote about similar topic yesterday. I proposed to validating commands using Pipeline Pattern – do validation before Command Handler execution but still in Application Services layer using Behaviors. What do you think about this solution? For me it is the “less trade-off” solution. http://www.kamilgrzybek.com/design/rest-api-data-validation/

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      Good approach. It ties back to my remark about the use of FluentValidator.

      I disagree with the segregation of different types of validation, though. Data validation _is_ business rule validation. The only reason why they are often segregated is to justify having two places to handle validation (e.g. FluentValidation and command handlers). This is often fine but a proper assessment is to say that it’s a trade-off: in this particular project, the convenience of FluentValidator is more preferable than pureness.

      • http://www.kamilgrzybek.com Kamil Grzybek

        I understand your point of view but I like this segregation, for me it is easier to understand and reason about system design. Sometimes the boundary between these types of validation is blurry. For example sometimes maximum length of property is system requirement (because you don’t want to store all strings as varchar(max) types in db), sometimes it is business rule (for example Driving License number has to have exact number of characters). After my article publication I have recently come across an Daniel’s Whittaker article http://danielwhittaker.me/2016/04/20/how-to-validate-commands-in-a-cqrs-application/. He wrote about similar segregation (superficial validation vs domain validation). The naming is different (maybe his is better, I don’t know) but approach is pretty the same.

  • https://davideguida.com Davide Guida

    interesting article as usual. I think that validating the commands as a part of the handlers is the way to go. Apart from sanity checks (empty strings, null and so on), there might be the need to hit the persistence layer and run more complex validations. I wrote something similar a while back, just a quick introduction to the topic: https://www.davideguida.com/cqrs-on-commands-and-validation-part-2-the-base-handler/

  • http://blog.langer.eu/ Alexander Langer

    Nice article. However, I tend to disagree a bit on the validation. 🙂

    For domain validation (like validity of an email address), I completely agree that this should NOT be validated within the command itself. In commands, an email property should be a simple string, and will only translated into an Email value object in the domain layer/command handler. So, any “domain invariants” should indeed be checked in the domain layer and not within the command (or client etc).

    However, commands are messages, and as such a contract between the caller and the callee. Therefore, you may very well define in the contract that, say, arguments/properties must not be null or empty strings etc. This are trivial checks that are even supported programmatically (say, by attributes) by many third party tools. C# will soon even incorporate non-nullable references as a language feature.

    If it’s part of the contract, in my opinion the contract should be enforced as early as possible – which is the creation time of the object (command).

    YMMV however on whether non-nullable fields or non-empty strings should be part of a contract. If you exchange messages with other systems that are not directly using the C#-classes but do, say, send JSON messages that are mapped to C#-classes, then you’d better check those in the command handler. If both, the callee and the caller are within the same system and use the *same* message classes, I prefer to enforce these invariants in the contract between callee and caller. Also helps a lot with unit testing.

    • http://davidkeaveny.blogspot.com David Keaveny

      It’s definitely a case of “why not both?”; if we’re talking C# then I use data annotations on the properties of the command object, to identify required fields, or set min/max string lengths/numeric ranges. That all gets picked up by a ModelValidatingCommandHandler decorator so it gets applied consistently across my commands. The other big plus here is that tools that generate API specifications (e.g. for Swagger/OpenAPI) will use those data annotations to mark up the specifications for API consumers.

      Then within each CommandHandler implementation, I will have validation of business rules (no changing historical pay rates on a cost centre that has been used in a payroll – not the sort of thing that can be expressed as a data annotation!); those validation errors will get returned using the same data structure as the data annotation failures, so that the client doesn’t have to handle the two different types of validations, well, differently.

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      Commands shouldn’t be raised by the application itself, all commands are coming from the outside of the app. You can’t really enforce a contract in such circumstance, all you can do is reject the command with a 400/4xx response.

      You are right that contract enforcement is a preferable behavior for classes communicating inside the same system. With commands, it’s always external systems calling your system, though, so fail fast doesn’t apply.

      • http://blog.langer.eu/ Alexander Langer

        Hmm, in your figure above, clients communicate with your system through an API (Controller), not through commands. External clients do not even know about those commands, they only use DTOs (as depicted in the figure).

        The contract in question is only between the API controller and the command handlers, which is not “from the outside of the app”. The API controller is an integral part of the application, and thus fail fast does apply. Even more, as David mentioned, the controller can use this contract to specify their own contract to the outside via Swagger/OpenAPI.