CQRS - how to model a scenario execution system
I recently started investigating CQRS and DDD for a green field project that I'm about to start. I studied a great deal of material from Udi Dahan, Greg Young, Mark Nijhof and others. These were really very helpful and I think I have a good understanding of the concepts. But, there are still certain questions on my mind on how I can apply these to my own domain.
My system will basically be a complex rules engine - in which rules will dictate the final price of certain products. The product definitions and rules will be entered into the system by administrators. Rules will be designed by administrators using a predefined set of properties that can have values from a predefined set, such as 'Purpose of Purchase' (Resell, Rent out) or free form values, such as Age.
Each product will have a base price, and rules will basically add/remove from the base price if they apply.
A very simple sample rule might be:
For product X, IF (Purchase Purpose = Resell and Age > 25) Add 25$ to base price.
So there are 2 kinds of users that use the system, administrators, who define the products, rules and base prices; and other users that query pricing based on a scenario that they enter in via a what-if UI.
My confusion here is this: running a scenario does not change the state of the domain at all, no other external system/person is interested in the result of the scenario execution but the running user himself/herself - it returns the result of a price calculation after running the applicable rules for the given scenario. For example, user might select Product X and query the pricing for a given scenario, such as (Purchase Purpose = Resell and Age = 40). Again, since this operation does not change the domain state at all, I guess it is a query. But, there is a rule engine operating on the scenario to calculate the final price, which I guess can be categorized as domai开发者_StackOverflow社区n logic being run. So - where does this logic belong? Is this a query that just works off of the read model, or is running a scenario a command that needs to be run in the domain model? Again, it feels like the domain layer is the place to be for these rules, but then how do I pass the result of the scenario execution to the user (feels like a query thinking about it this way). Or maybe, CQRS is not the right solution for this particular problem?
I had this exact issue in my own domain (e-scheduling 4 healthcare). Basically the system is configured using a domain model (write side). This would be defining rules, products and base prices in your domain. What comes out of the domain? Events, state changes, things that happened along with why it happened. Now what I did was consume these events in a different Bounded Context, in my case a complex search engine that finds free slots in the schedules of doctors, operating theaters, and expensive equipment. This could be a route you could take as well, consuming your product, base price, and rule related events and store them in such a way that the rule engine, sitting on top of that data, can handle user requests for scenarios as efficiently as possible. Most likely you'll find out that the model to store changes (domain) differs from the model optimized to query those what-if scenarios (rule engine). Your domain will probably have rules like "you can't specify the same product twice" or "this rule will never be matched (age < 25 && age > 25)". The domain is concerned with only allowing valid state changes. This is not a concern of the rule engine. You'll be tempted to reuse concepts/classes in your rule engine that are defined in the domain. Resist that urge. Question if they really serve the same purpose. Modelling it twice for a different purpose is not dirty or a violation of DRY.
CQRS states nothing about that there shouldn't be domain logic in the query part of the application. If it's possible and practical then it's ok to have separate denormalized query stores for every aspect or even query of your application but of course it is not necessary.
In short, a query is a query, no matter how complex the task of finding it's answer.
精彩评论