28

I started with reading about CQRS and I'm little confused.

Is it allowed to call the read side within the write side for getting additional informations?

http://cqrs.nu/Faq/command-handlers here they say it is not allowed, but in the cqrs journey code I found that they call a service 'IPricingService' which internally uses a DAO service class.

So what I must do to get additional informations inside my aggregation root?

Thomas Geulen
  • 590
  • 7
  • 22

4 Answers4

36

CQRS Journey should not be seen as a manual. This is just a story of some team fighting their way to CQRS and having all limitations of using only Microsoft stack. Per se you should not use your read model in the command handlers or domain logic. But you can query your read model from the client to fetch the data you need in for your command and to validate the command.

Since I got some downvotes on this answer, I need to point, that what I wrote is the established practice within the pattern. Neither read side accesses the write side, not write side gets data from the read side.

However, the definition of "client" could be a subject of discussion. For example, I would not trust a public facing JS browser application to be a proper "client". Instead, I would use my REST API layer to be the "client" in CQRS and the web application would be just a UI layer for this client. In this case, the REST API service call processing will be a legitimate read side reader since it needs to validate all what UI layer send to prevent forgery and validate some business rules. When this work is done, the command is formed and sent over to the write side. The validations and everything else is synchronous and command handling is then asynchronous.

UPDATE: In the light of some disagreements below, I would like to point to Udi's article from 2009 talking about CQRS in general, commands and validation in particular.

Alexey Zimarev
  • 17,944
  • 2
  • 55
  • 83
  • 2
    I disagree. 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 clearly exposes too much of the command validation / domain knowledge to the client and contradicts that the client only wants to express an intent. IMHO a better solution is to provide an `PricingService` interface (which are part of the ubiquitous language) to your aggregate roots and then implement the interface as needed - which might include querying the read side. – Alexander Langer Jul 12 '15 at 08:01
  • I'll have to second this one. – JoG Jul 12 '15 at 21:39
  • 2
    @AlexanderLanger This is not something I invented, this is how the pattern is designed. You might find it possible to query the read side from your command handler, but this will something else than the pattern in question. If you look at any diagram on CQRS you will never see that read model is queried by the write mode. It is only read by the client. – Alexey Zimarev Jul 13 '15 at 07:56
  • 3
    The client should always operate in good faith that the commands it issues will succeed. Your command handlers shouldn't need to call the read side to validate. In the unlikely event that you get two contradictory commands whose effects may conflict (for example, two users attempting to create accounts with the same email address) you should have a process manager issue a corrective action. The fact that the command's effect was countered may not be significant in terms of your domain; the fact that it was despatched in the first place still stands. – Matt Jul 13 '15 at 12:13
  • @AlexeyZimarev If you think Design Patterns are hard templates and must not be adjusted to the respective situation, then just let the `PricingService` implementation query the database directly and not the read model. – Alexander Langer Jul 13 '15 at 15:32
  • 9
    (1) You are perverting my comment, I did not say that design patterns are hard templates. (2) What "database" are you talking about? Write model works with aggregates, it can only fetch one or mode aggregate from a given BC, by aggregate id. (3) Design patterns (btw CQRS is not really a design pattern, neither DDD is) are written in blood, I have seen too many times when people put ORM in place, create a data model and call it a "domain". And when I tell them they have an anaemic model, they say that DDD is not written in stone and can me manipulated to the developer comfort. No thanks. – Alexey Zimarev Jul 13 '15 at 15:45
  • I'm really struggeling with this one. Lets say your Order Domain wants to call a `TaxCalculationService`, but you want to use some external webservice. Do you really want your write side to block on an external service and potentionally fail because of this. But i don't really see any other viable options. – JoG Jul 18 '15 at 20:35
  • 5
    Your domain is unable to call an external service from a command handler. Command handler should operate within a bounded context. This goes even beyond the original question (and answer). – Alexey Zimarev Jul 19 '15 at 16:40
  • @JoG Probably you should call TaxCalculationService from your Client/UI and append the results to the order data when the order is placed (call to your orders service) and the command is triggered. In this way, it already has the taxes and doesn't need anything from any external services. – adridev Aug 16 '17 at 16:37
  • So can we use the public API of read side in write side , before the command dispatch to command handler – Ashwani Tiwari Jun 30 '18 at 18:21
  • 3
    My comment above is not entirely correct (or I can tell - incorrect). You _can_ call external services from anywhere, using, for example, a domain service. The book "Patterns, Principles, and Practices of DDD" gives some good examples of this approach. Usually, this is not a responsibility of the command handler to do this, the aggregate should be responsible to check its own invariants. But it is not related to the accessing read side from the write side. The client should be assessing the read side. – Alexey Zimarev Jun 30 '18 at 20:45
  • @AlexeyZimarev Means the making of command should done on client by the help of read side API ( “The client should be assessing the read side” as in your comment) because the client can access the read api without any problem. Is am correct understand. – Ashwani Tiwari Jul 07 '18 at 15:40
  • If write-side needs to enforce unique constraints, this is not possible without calling the read-side. To solve this dependency issue, you may define an Interface (packaged with write-side) that the read side should implement (IoC). In other world I do not think this is a problem of CQRS. – adnanmuttaleb Dec 22 '19 at 12:50
5

The CQRS FAQ (http://cqrs.nu/Faq) suggests:

"How can I communicate between bounded contexts?

Exclusively in terms of their public API. This could involve subscribing to events coming from another bounded context. Or one bounded context could act like a regular client of another, sending commands and queries."

So although within one BC its not possible to use read-side from write-side and vice-versa, another bounded context or service could. In essence, this would be acting like a human using the user interface.

Ashley Aitken
  • 2,419
  • 2
  • 20
  • 24
1

Yes assuming you have accepted the eventual consistency of the read side. Now the question is where. Although there is no hard rule on this, it is preferable to pass the data to command handler as opposed to retrieving it inside. From my observation there are two ways:

  • Do it on domain service

Basically create a layer where you execute necessary queries to build the data. This is as straightforward as doing API calls. However if you have your microservices running on Lambda/Serverless it's probably not a great fit as we tend to avoid a situation where lambda is calling another lambda.

  • Do it on the client side

Have the client query the data then pass it to you. To prevent tampering, encrypt it. You can implement the decryption in the same place you validate and transform the DTO to a command. To me this is a better alternative as it requires fewer moving parts.

inmyth
  • 8,880
  • 4
  • 47
  • 52
  • By moving the burden to collect data to the client, you have to consider which client you are talking about, because on a web/mobile client it means "wasting" bandwidth And of course the added complication needed to prevent tampering, etc... means performance implications – Not Important Apr 07 '22 at 08:22
0

I think it depends. If in your architecture the "command side" updates the projections on real-time (synchronously) you could do that calling the query api. (although that seems strange)

But, if your projections (query side) is updated asyncronously would a bad idea to do it. Would be a posibility to get a "unreal" data.

Maybe this situation suggests a design problem that you should solve.

For instance: If from one context/domain you think you need information from another, could a domain definition problem.

I assume this, because read data from itself (same domain) during a command operation doesn't make much sense. (in this case could be a API design problem)

Hermes Monteiro
  • 101
  • 1
  • 3