31

I've recently read the article CQRS à la Greg Young and am still trying to get my head around CQRS.

I'm not sure about where input validation should happen, and if it possibly has to happen in two separate locations (thereby violating the Don't Repeat Yourself rule and possibly also Separation of Concerns).

Given the following application architecture:

#      +--------------------+           ||
#      |    event store     |           ||
#      +--------------------+           ||
#           ^          |                ||
#           |  events  |                ||
#           |          v                  
#      +--------------------+         events         +--------------------+
#      |      domain/       | ---------------------> |   (denormalized)   |
#      |  business objects  |                        |  query repository  |
#      +--------------------+           ||           +--------------------+
#         ^   ^   ^   ^   ^             ||                      |
#         |   |   |   |   |             ||                      |
#      +--------------------+           ||                      |
#      |    command bus     |           ||                      |
#      +--------------------+           ||                      |
#                ^                                              |
#                |             +------------------+             |
#                +------------ |  user interface  | <-----------+
#                  commands    +------------------+        UI form data  
  • The domain is hidden from the UI behind a command bus. That is, the UI can only send commands to the domain, but never gets to the domain objects directly.

  • Validation must not happen when an aggregate root is reacting to an event, but earlier.

  • Commands are turned into events in the domain (by the aggregate roots). This is one place where validation could happen: If a command cannot be executed, it isn't turned into a corresponding event; instead, (for example) an exception is thrown that bubbles up through the command bus, back to the UI, where it gets caught.

Problem:

If a command won't be able to execute, I would like to disable the corresponding button or menu item in the UI. But how do I know whether a command can execute before sending it off on its way? The query side won't help me here, as it doesn't contain any business logic whatsoever; and all I can do on the command side is send commands.

Possible solutions:

  • For any command DoX, introduce a corresponding dummy command CanDoX that won't actually do anything, but lets the domain give feedback whether command X could execute without error.

  • Duplicate some validation logic (that really belongs in the domain) in the UI.

Obviously the second solution isn't favorable (due to lacking separation of concerns). But is the first one really better?

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268

2 Answers2

9

I think my question has just been solved by another article, Clarified CQRS by Udi Dahan. The section "Commands and Validation" starts as follows:

Commands and Validation

In thinking through what could make a command fail, one topic that comes up is validation. Validation is different from business rules in that it states a context-independent fact about a command. Either a command is valid, or it isn't. Business rules on the other hand are context dependent.

[…] Even though a command may be valid, there still may be reasons to reject it.

As such, validation can be performed on the client, checking that all fields required for that command are there, number and date ranges are OK, that kind of thing. The server would still validate all commands that arrive, not trusting clients to do the validation.

I take this to mean that — given that I have a task-based UI, as is often suggested for CQRS to work well (commands as domain verbs) — I would only ever gray out (disable) buttons or menu items if a command cannot yet be sent off because some data required by the command is still missing, or invalid; ie. the UI reacts to the command's validness itself, and not to the command's future effect on the domain objects.

Therefore, no CanDoX commands are required, and no domain validation logic needs to be leaked into the UI. What the UI will have, however, is some logic for command validation.

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • 1
    I deal with CQRS from an ASP.NET MVC perspective (for better or worse) and my controllers, which create and issue the commands, really just perform a minimal amount of actions. Validating input sent from the client to determine whether the command should be issued or not and preparing the view. My business logic is contained in my domain and does not leak to the UI. I think you're heading in the right direction here. Good luck! – David Hoerster Mar 07 '11 at 12:20
  • 2
    But I think you might still want CanDoX *queries* in order to grey out certain commands in the UI. – Josh Kodroff Feb 09 '12 at 15:46
  • CanDoX might be used by an authorization service / layer made specifically for the query side. CanDoX sounds like an authorization check for viewing something. CanDoX == IsAuthorizedToDoX (CanViewX/IsAuthorizedToViewX) . Most of the CanDoX of the command side should be designed in the model itself. Can a user be an author? Can a book be change by an author, these are part of the ubiquitous language – Tudor Jun 19 '14 at 21:33
  • 1
    @Tudor: Do you know that British comedy sketch where the difference between "can" and "may" is explained? One of the relevant quotes from it would be: ["You `Can`, but you `May` not."](http://english.stackexchange.com/questions/54340/difference-between-can-and-may) (Link doesn't go to to the sketch because I cannot find it anymore. :-) – stakx - no longer contributing Jun 19 '14 at 23:07
  • @stakx :) Yes "may" is a better word for describing what a user should be allowed to do. – Tudor Jun 20 '14 at 07:52
  • This is terrible from a user perspective though. Say a command requires a user to fill in 20 fields, would you let them fill in those 20 fields only to then tell them that the command cannot be executed because of a business rule? – user247702 Aug 11 '16 at 12:21
  • @Stijn: Off the top of my head, I can think of two things: **a)** Perhaps you need to make the entry form smaller, or divide it into several steps (aka wizard). **b)** Is it *really* so terrible when you click on some *Submit* button, the application will spend a small amount of time processing, then you're told that you need to re-submit your data, with this-and-that fixed? Happens often enough in reality. – stakx - no longer contributing Aug 11 '16 at 12:40
  • Maybe I should provide more context. I'm working on a level 3 REST API that exposes the available commands. Some of those commands may only be executed when a domain entity and some of its related domain entities are in a certain state. It doesn't feel right to tell a client that command X is available at endpoint Y, but on actual execution disallow the command because of the current state (which is unrelated to the command parameters). (P.S. I'm still getting familiar with DDD and CQRS, in case some things I say don't make a lot of sense.) – user247702 Aug 11 '16 at 12:55
  • @Stijn: I'll try to explain using an analogy. Imagine you're at the supermarket, and you're about to pay. Before you approach the cashier, you need to have some things ready: namely, money (can be cash, a bank's debit card, etc.). Now when you pay using that money, things can *still* go wrong (you paid with coins, but miscounted them and you don't have enough cash with you, or you pay with a card but there aren't sufficient funds on your bank account), so you will have to fix that first and then try paying again. – stakx - no longer contributing Aug 11 '16 at 15:10
  • @Stijn: Preparing your money before paying is like command preparation / validation; the cashier checking your coins or the bank checking your funds is the business rule part of validation. Perhaps not the best of examples, but I hope this helps to show that sometimes you won't know whether an action will succeed until you actually go ahead and try. It happens in the real world, it doesn't necessarily have to feel wrong. – stakx - no longer contributing Aug 11 '16 at 15:13
2

Client-side validation is basically limited to format validation, because the client side cannot know the state of the data model on the server. What is valid now, may be invalid 1/2 second from now.

So, the client side should check only whether all required fields are filled in and whether they are of the correct form (an email address field must contain a valid email address, for instance of the form (.+)@(.+).(.+) or the like).

All those validations, along with business rule validations, are then performed on the domain model in the Command service. Therefore, data that was validated on the client may still result in invalidated Commands on the server. In that case, some feedback should be able to make it back to the client application... but that's another story.

Roy Dictus
  • 32,551
  • 8
  • 60
  • 76
  • thanks for answering and confirming the understanding I've arrived at. What I *didn't* realise at the start was that there's a difference between validating a command against the domain's current state, and validating the command *itself*. I entirely missed the latter point and thought that both are the same thing and happen in the domain; now it's clear to me that only the former validation step happens in the domain; and only the latter is ever reflected in the UI by such means as disabled command buttons etc. – stakx - no longer contributing Mar 11 '11 at 08:57
  • 2
    I would like to hear how the feeedback is going back to client (except for email story.) – Alex Burtsev Apr 19 '12 at 21:36