20

I am learning DDD and making use of the CQRS pattern. I don't understand how to validate business rules in a command handler without reading from the data store.

For example, Chris wants to give Ashley a gift.

The command might be GiveGiftCommand.

At what point would I verify Chris actually owns the gift he wants to give? And how would I do that without reading from the database?

chris
  • 6,653
  • 6
  • 41
  • 54
  • 2
    Have a look at this http://williamverdolini.github.io/images/cqrses/CQRS-ES-architecture.png – Sir Rufo Aug 27 '15 at 07:16
  • 1
    If a gift has a sense of "ownership", and the gift would "remember" that Chris is the owner, then upon ``gift.Give(giver: chris, receiver: ashley)`` the gift could verify ``chris`` (the variable that refers to Chris as either an entity or value object) is indeed the owner. – Yves Reynhout Aug 27 '15 at 09:57
  • @YvesReynhout and how Gift would know the owner Chris really exists? :) – Eugene Aug 18 '16 at 09:05
  • At the time the gift comes into existence, using the giver as a factory at that point. Obviously, you're only sure the system ever knew somebody who registered as Chris. – Yves Reynhout Aug 19 '16 at 08:32

3 Answers3

19

There are different views and opinions about validation in command handlers.

Command can be rejected, we can say No to the command if it is not valid.

Typically you would have a validation that occurs on the UI and that might be duplicated inside the command handler (some people tend to put it in the domain too). Command handler then can run simple validation that can occur outside of the entity like is data in correct format, are there expected values, etc.

Business logic, on the other hand, should not be in a command handler. It should be in your domain.

So I think that the underlying question is...

Should I query the read side from Command Handlers?

I would say no. Do not use the read model in the command handlers or domain logic. But you can always query your read model from the client to fetch the data you need in for your command and to validate the command. You would query the read side on the client to check would if Chris actually owns the gift he wants to give. Of course, the validation involving a read model is likely to be eventually consistent, which is of course another reason a command could be rejected from the aggregate, inside the command handler.

Some people disagree saying that if you require your commands to contain the data the handler needs to validate your command, than you can never change the validation logic within your handler/domain without affecting the client as well. This exposes too much of the domain knowledge to the client and go against the fact that the client only wants to express an intent. So they would tend to provide an GiftService interface (which are part of the ubiquitous language) to your command handler and then implement the interface as needed - which might include querying the read side.

I think that the client should always assume that the commands it issues will succeed. Calling the read side to validate the command shouldn't be needed. Getting two contradictory commands is very unlikely (users creating accounts with the same email address). Then you should have a mean to issue a corrective action, something like for example a Saga/Process Manager. So instead making a corrective action would be less problematic that if the command could have been validated and not dispatched in the first place.

demongolem
  • 9,474
  • 36
  • 90
  • 105
Tomasz Jaskuλa
  • 15,723
  • 5
  • 46
  • 73
  • 1
    I've not done a lot of this type of thing...but I would have thought that the read model(s) is just a different representation of the data that is contained in the domain. Shouldn't the domain be able to process the command using its own data store? Any errors could ripple through the system as any other event/piece of data. – chosenbreed37 Aug 27 '15 at 10:04
  • 3
    The domain model is command oriented. It's structure doesn't allow always to query efficiently it's own data if spread between several aggregates. It would couple aggregates roots in an artificial way and this wouldn't be efficient. – Tomasz Jaskuλa Aug 27 '15 at 10:10
  • 5
    The read model is just a projection of the truth and can be behind the real truth. So you have to keep that in mind, when asking the read model. – Sir Rufo Aug 27 '15 at 10:11
  • Yes, that's why it's always to ask how many commands can fails due to stale data and how business would like to handle it. You could have a process manager issue a corrective action. – Tomasz Jaskuλa Aug 27 '15 at 10:13
  • 3
    Also from further discussion in the cqrs google group I learned some things. A command handler should call a method on the aggregate root to apply the command. The Aggregate Root would load the event stream on initialization and the end result would be the current state of the aggregate. You could then do some business rule enforcing with that current state. – chris Aug 27 '15 at 15:22
  • Correct, if only you have enough data to do it inside the aggregate. Otherwise the rest I said apply. – Tomasz Jaskuλa Aug 27 '15 at 15:23
  • 1
    @Chris You're confusing CQRS with Event Sourcing, very different concepts. – MikeSW Aug 27 '15 at 15:27
  • @TomaszJaskuλa Saying that `Business logic, on the other hand, should not be in a command handler.` is like saying "Business logic doesn't belong in a function" . A domain use case is a service, a command handler is a service. Any service using domain concepts according to business rules belongs to Domain. If I choose to express the service as a command handler, that's an implementation detail. In the end it's just a function. Someone doing FP would probably use a static method for that purpose. – MikeSW Aug 27 '15 at 15:32
  • 4
    What kind of service are you talking about? I assume domain service. For my part I treat command handlers as application services, so no business logic there. Just orchestrating use case. – Tomasz Jaskuλa Aug 27 '15 at 15:36
  • @Stijn - Are you linking to the correct answer? What wording is copied in this one? I'm not seeing any plagiarism here. – Brad Larson Aug 11 '16 at 15:54
  • I think I am aligned with everything here. So @TomaszJaskuλa, would you say that validation is done on 2 layers? 1) the transport layer: has the data been passed in the correct format? Example: is there a value present/did the user pass a number/etc 2) the business layer: is the operation acceptable from a business stand point? Example: can users buy more than 10 apples at a time? So would you say 1) belongs in the controller while 2) belongs in the aggregate? – alaboudi Oct 25 '22 at 15:26
3

It depends if the operation is async or not i.e does the user expect some immediate response. Gift ownership is basically a security feature and that can be done as a 'prep' operation before invoking the actual service or sending the GiveGiftCommand.

The only command validation you can do is to make sure it contains the data in the required format (UI validation) and that the user has the permissions to do that action. But after the command is sent it's up to the Domain to decide if other business constraints are respected.

If the user expects some immediate feedback, you can actually 'wait' until the command is completed and for that you can use an approach where a command handler can provide a result to the sender using a mediator . But this implies that at least some commands are executed in an immediate manner and that might not be the case in your app. However, this is the simplest approach if you want to just return a message error as opposed to implementing compensations and other stuff. Some use cases are simple.

About command handlers and business logic, I disagree with Tomasz Jaskuλa . A command handler is a function, a technical detail. You can put business logic in a command handler or a static function, it doesn't matter. Messages and their handlers are infrastructural components that can be used to implement functionality. For example, in an app you can have Domain Events, Application Events etc . They're all events i.e notification that something changed and you can have event handlers that reside in Domain or in other places.

There's no rule preventing you to 'read' from the db, however at least the read model theoretically is stale. However this might not be such a problem in 99% of cases. For the rest 1% you need very specific solutions.

Martin Liversage
  • 104,481
  • 22
  • 209
  • 256
MikeSW
  • 16,140
  • 3
  • 39
  • 53
0

I just asked the exact same question from a knowledgeable friend of mine and his answer was that it is OK to do this validation inside the command handler (in my case inside an akka persistent actor that interprets commands and writes events to the journal).

However if that is not possible for performance reasons (because processing validation inside a persistent actor would block the actor and that would be a scalability bottleneck for the whole app) then optimistic locking (OCC) can be used.

In other words the validation can be performed in an other actor (lets call it the validator actor - which is not in the persistent actor) , this will not block the persistent actor but it might happen that the data that is used for the validation has changed in the persistent actor while the validation was running in the validator actor) .

If the validator actor returns with an OK and all the data that has been used for the validation is still the same in the persistent actor (has the same version - version as in OCC) as it has been at the point when the command arrived to the command handler (persistent actor) then the command is accepted by the persistent actor , otherwise the validation needs to be resubmitted for re-evaluation to the validator actor.

jhegedus
  • 20,244
  • 16
  • 99
  • 167