Cqrs question; should domain objects and business rules be separated? RRS feed

  • Question

  • Ok not strictly Cqrs but it has highlighted the question for me. Is it a recommended practice to separate out business rules and domain behaviour? So an Employee object may have an IsValidState method but that would typically *only* check that the essential details are correct e.g. age > 15, name.length>1. A separate activity, such as a denormalizer in cqrs, would implement the business rules, e.g. We have received 3 references for the Employee, the Employee code is valid (not duplicate), etc. My worry is that doesn't this delegate the bulk of the domain logic elsewhere?
    Monday, December 20, 2010 9:19 AM

All replies

  • Well CQRS is all about separating the command from the read object(s). Thus allowing you to have different read and write types.  So I would think your validation logic goes in the command object.

    Once you're reading data out your database, it's a bit late to go validating your data.

    That bit I think I'm clear on.

    I'm less clear what you mean by separating business rules and domain behaviours.  I would have thought business rules in some sort of business/domain layer watchamacallit drive behaviours in the view.  And or  processing layers in some instances.  So aren't they two different things by definition?

    Monday, December 20, 2010 10:59 AM
  • Command Validation is about validating the types involved in the command are correct, i.e. it's a good and sensible command. Where I start to wonder is about more complicated business rules. If you have a complicated business rule, that may take an long or even indeterminate time to complete, then you don't want to do that in the command. Typically the UI has issued the command and is waiting for at least the command to complete. To avoid blocking the UI I might use and Event bus to allow interested handlers/denormalizers to process the command-event(s). So you could have business rules 'subscribing' to domain events and therefore the long running rule can be evaluated without blocking the UI. HOWEVER, this means that you're now separating out the rules from the domain which would weaken the domain model. Phew, hope that helps.
    Monday, December 20, 2010 10:01 PM
  • Thanks for the interest Phijo MP, might want to tone it down a touch.
    Monday, December 20, 2010 10:03 PM
  • Is this just sticking a fancy name on something already has a name?

    Batch load kind of works for me as a label.

    Processes which take a signicant time to carry out are best decoupled.

    I see this most commonly with ETL functionality.  With DTS and now SSIS jobs my "Plan A" for batch load from another completely separate system is to write to import table(s).  Then a series of validation steps.  Then import to the "proper" tables the data which passes and write to exception tables for human review that which does not.

    Another situation is interfacing between disparate systems where you need to decouple.  Interfacing data to and from microsoft Dynamics CRM being one specific example I encountered.  CRM performed really badly and I was concerned about bring it to it's knees.  Plus I knew there was a probable requirement for dialing from a remote site.  CRM exposes a web service interface for writing records - batch load to the database is not an option. My solution was to decouple using message queues and have a windows service trickle feed the thousands of records and write results to a result queue for later checking.

    Both of these are batch processing of sorts.

    I've also read abouty occasional connected systems patterns.  The nature of observable collections and MVVM does enable delayed reporting of batch process failures.   There's a pattern for remote mobile apps where occasional connection is handled by queueing all transactions and writing results to a repository.   That's batching in a different thread. 

    Another option would be to fire off WWF processes.  Having tried that, I can't say I'd recommend that if you could possibly avoid it.  You can fire off a process which goes and does all sorts.  Not batch but there again not what i'd associate with a domain object really.  One might be involved but it's a separate process where all the action takes place.

    I dunno.

    Seems to me what all these solutions have in common is a separate mechanism to the object stuff which is necessary in order to carry out the asynchronous validation.  You could call SSIS the "input domain" or something but it's still a batch load process.

    Tuesday, December 21, 2010 10:35 AM
  • Although I don't see it as a batch process the problem does share very similar issues. So I might choose to use a WF/Saga to implement some form of long running query, but my point is really about the async nature. One of the adv. of a cqrs pattern is that anything "on the other side" of the event bus could be fire-and-forget. So it's not a case that I don't know if it's long running, I don't want to care! Once you've gone down that route then the temptation is farm as much of the logic into the "don't care" section as possible. This is great because the domain's business rules can get as complicated and long running as it want's the bus (and appropriately written UI) will take the strain. What I want to know is if this is indeed how people are implementing cqrs systems because the worry is that the domain model is now separated out to those bits of logic that are known to run very quickly and those that may/may not run slowly. Even writing that last sentence shows how difficult it would be to maintain.
    Thursday, December 23, 2010 1:25 PM
  • Thought I'd add this link as it might help explain my question;

    Sunday, January 9, 2011 5:37 PM
  • I think I understand the question.

    It's the practicalities of bolting on a batch process to a screen which concern me.

    What do you do when something fails validation and the user has already closed his browser?

    Emailing confirmation or queueing success/fail transactions for review are the obvious solutions spring to mind.  Both add a degree of complication.

    The devs I've read talking about actually using WWF as a process which is fired off by the user clicking a button don't seem so keen on that level of indirection. 

    Maybe it's significant that nobody is owning up to have adopted asynchronous validation in this way.



    Monday, January 10, 2011 2:21 PM
  • TBH in the real world outside of computers we're quite used to the async nature of things, even with technology if the expectation is correctly set...take this forum as an example. But I think there is certainly a question of SLA vs User expectation, that is to say that if a service cannot respond under a web response SLA (e.g. 3 secs) them the UX must be altered to make the user expectation seem natural. That is very much on case-by-case basis. So for booking a hotel you'd expect to get an email confirmation. For changing the volume of an mp3 player you'd expect that to be instant. So it's your typical horses for courses, if you can do it near real-time for a good ROI then go sync, if you can't then you can't and have to implement an async solution. The cqrs aspect is about helping with the async rather than forcing aysnc everywhere. Thanks for helping me get there.
    Wednesday, January 19, 2011 3:11 PM