mardi 12 avril 2016

Is running a query from a command a violation of Command-Query Separation?

Given a real-world anonymous shopping cart, the "AddToCart" workflow must do the following steps:

  1. Lookup the current product from the database. Get the price from the product or use a service to calculate the price on user selections and other product properties. (query)
  2. Lookup the current shopping cart from the database. (query)
  3. If the current shopping cart doesn't exist in the database, create a new shopping cart entity (in memory).
  4. Add the new item (product) to the shopping cart entity (in memory) along with its price.
  5. Run any discount calculations on the entire shopping cart. (depends on query)
  6. Run any sales tax calculations on the shopping cart. (depends on query)
  7. Run any shipping calculations on the shopping cart. (depends on query)
  8. If this is a new shopping cart, add the entity to the database, otherwise update the shopping cart in the database. (command)

So, although "AddToCart" sounds like it should be a command (since it updates the system state), in practice it depends on many queries.

My Question

What is the generally accepted way to handle workflows like this?

  1. Make an AddToCartCommandHandler that depends on other services that may run queries.
  2. Make a facade CartService that orchestrates the workflow that runs the queries first followed by the commands.
  3. Make the controller action method first run the queries, then run any commands. Seems like some of the query steps could be missed if this needs to be reused.
  4. Other?

Is the reason I can't find an answer about this because it "depends on the design" and this is one of the exceptions where not to apply it?

If the commands and queries are separated, would I pass my real entity framework entity class to the command that adds/updates the cart (so EF can work out whether it is attached or not)? It seems like a DTO won't do in this case.

NOTE: I am implicitly assuming that systems that implement CQS do so with the aim that eventually they could become a full-on CQRS system. If so, this workflow apparently would not be able to make the transition - hence my question.

Background

I am taking my first stab at CQS.

It is clear from the documentation I have read about this pattern that a query must not change the system state.

However, it is unclear whether it is considered okay to run a query from within a command (I can't seem to find any info anywhere).

There are several real-world cases I can think of where this needs to happen. But, given the lack of real-world examples of this pattern online I am uncertain how to proceed. There is lots of theory online, but the only code I can find is here and here.

Aucun commentaire:

Enregistrer un commentaire