views:

526

answers:

4

A lot of the blogsphere articles related to CQRS (command query repsonsibility) seperation seem to imply that all screens/viewmodels are flat. e.g. Name, Age, Location Of Birth etc.. and thus the suggestion that implementation wise we stick them into fast read source etc.. single table per view mySQL etc.. and pull them out with something like primitive SqlDataReader, kick that nasty nhibernate ORM etc..

However, whilst I agree that domain models dont mapped well to most screens, many of the screens that I work with are more dimensional, and Im sure this is pretty common in LOB apps.

So my question is how are people handling screen where by for example it displays a summary of customer details and then a list of their orders with a [more detail] link etc....

I thought about keeping with the straight forward SQL query to the Query Database breaking off the outer join so can build a suitable ViewModel to View but it seems like overkill?

Alternatively (this is starting to feel yuck) in CustomerSummaryView table have a text/big (whatever the type is in your DB) column called Orders, and the columns for the Order summary screen grid are seperated by , and rows by |. Even with XML datatype it still feeel dirty.

Any thoughts on an optimal practice?

+1  A: 

if anyone is actually saying that your viewmodels should be flat, they are either oversimplifying their example or they are talking a bunch of nonsense. hierarchical data is not bad and should not be avoided in your viewmodels.

there really are no 'best practices' for this, though. it's all very subjective in how you load up the data. you need to find a solution that works well for your current team and system. and you should also understand what other options are out there because you'll probably run into a situation where your current solution is inadequate.

here are some of the ways I handle this, depending on the application i'm working on, in C# / .NET:

  • Datasets and straight ADO.NET, and bind the dataset directly to the screen's controls ** write straight SQL code to load the dataset ** use views in the database to load the dataset ** use stored procs to load the dataset

  • NHibernate and DTO / Viewmodel objects ** i typically use views when going down this route - I'll create a suite of views on top of my domain's schema, that denormalize the data into the model i need, and then use NH to load it up via a second set of maps

  • DTO / Automapper from domain model ** i don't like this approach unless I know that I already have everything from my domain model loaded in memory. i'll use a tool like Automapper to transfer data from my domain model into a DTO / ViewModel

i'm sure there are other options, but these are the three that i use most often, in order of how often i use them. they all have their own cost / benefits. but the important thing to understand is that you can and should retrieve the data in a manner that makes it easy for you to populate your screens.

Derick Bailey
Don't really see the need to use a ORM to get data from a denormalized table (viewmodel). I recommend Udi Dahan's video-lecture on CQRS, where he emphasis this. http://www.udidahan.com/2010/02/26/cqrs-video-online/
Commander Keen
it's certainly not a need. as i said, it's one option. i've used it a few times in situations where it did not make sense to introduce another data access methodology. however, it does come with a cost and is not appropriate for every situation.
Derick Bailey
+2  A: 

If you want to work with different dimensions in your views, there are no problems to do that. There is noting saying you cant use multiple view models below a view. The denormalizer is responsible for populating the database views with correct data. Have a look at this post, it explains how the denormalizer works and may put you in the right direction concerning your question.

Fossmo
+6  A: 

Yeah, there's a confusion that arises. Here's how it happens: First, in order to really help new people understand what CQRS is all about, and to really drive home how it differs from the typical layered architecture, people say things like, "Your view models can be completely flat", and "You should have one table per view model in your Query database."

But that is really just meant to drive the point home ... it is not true that you must have only one table per view model (though in most cases you probably should). What those statements are trying to say is this: "You've got to shake yourself free of some rules that you've followed for so long about normalization. With the CQRS architecture, you have the opportunity to make database tables in your Query channel that are completely shaped according to the needs of your view and nothing else. Make sure you take full advantage of that. Don't go halfway by normalizing these tables just because it is what you're accustomed do. Instead, go ahead and do things that used to be considered unthinkable, such as making one database table per view model, or making your view model tables completely flat."

There are still cases such as yours where the schema that would best serve your needs would have multiple tables. You might even (God forbid) do a Join or two. That's fine, as long as you really have designed the database tables to serve your view, and not vice versa. But be careful, it is easy to slip down the slope of normalization and sharing data between many views in the Query database. Don't go there ... there's simply no reason and it incurs more cost than benefit. The main goal is this: Your View logic should be dead, dead simple. You want the intelligent rules living on the Command side of the house, and a little bit in the Subscribers that populate the data in the Query channel. So the code that reads from the Query database and shows data on a screen should be dead simple (almost as simple as a "passive view").

Update: As further backing for the statement that it is not "forbidden" to do some joins as long as you have designed the database shape to best serve the task you're achieving, consider OLAP. The star schema is a perfect example of a database schema designed to support reads, that fits perfectly in the Query side of CQRS, and that does involve joins. The joins are kept simple, and they are in place to further enhance the goals of the Read tasks performed against the database.

Charlie Flowers
A: 

I think people are missing the point of CQS (or CQRS, same thing really). CQR is simply a pattern to say that you should have separate models for read and writing. What those model are is completely up to your implementation requirements.

Folks that been talking about this recently usually describe extremely simple architectures and implementation to drive home that the fact that most enterprise software written today is over-designed and over-engineered.

Joseph Daigle