Sponsored By Aspose - File Format APIs for .NET

Aspose are the market leader of .NET APIs for file business formats – natively work with DOCX, XLSX, PPT, PDF, MSG, MPP, images formats and many more!

The catalogue metaphor and command-query seperation architectures

Command-Query separation is being popularized today with architects like Greg Young
and Udi Dahan as a way of architecting systems. It can be hard to grasp as a concept, even if we understand command-query seperation as a design pattern that influences the methods on our classes. It can be difficult to see how the principle scales to the level of architectures.

Pat Helland’s article Data on the Outside vs. Data on the Inside remains key for me in trying to understand this model. Pat distinguishes between operators and operands. Operators are commands, things we can do like order a meal, or order a book. Operands are the data that we use for that command. So order a Thai Green Curry, or orderDan Bropwn’s The Lost Symbol. This implies that we have to publish those operands so that people can discover them to use in the command. A way to think of this list of operands is as catalogue data.

I find that the XP idea of an architectural metaphor helps me to
understand the seperation between operator and operand when architecting a solution.

If I want to order a take-away from the Thai restaurant I need a menu that tells me what they deliver and how much it costs. The menu is not the food itself, it’s just an number, a name, and a price I can use to order the food with. Catalogue data has some interesting characteristics such as often being cacheable because it changes infrequently, or being versioned if we can deal with different varieties of it. But the key to this discussion is to appreciate that in order to carry out the task of ordering a takeway I need first to have a menu that lets us communicate about what I can order. In patterns terms I need to query for the food menu, and then issue the command to order the food.

Now in software we have the same need to present a user with catalogue data so that they can carry out a task. We have to tell them what operators are valid for our operands. This is where the query side of command-query comes in when thinking about command-query architectures. The query builds the catalogue – it grabs the list of acceptable operands for our operators.

This is often easy to comprehend in the context of MVC architecures. When I get a request for a page that allows you to perform a task, I want to populate it with my operands. For example, if I want to enable the task of ordering food I need to
give you a menu. I do not want to load my food or customer entities for
this, because all I need is the name for you to display in  a pick list
(and possibly an id). When you perform the task, ordering the food, then I may need to
load the customer or food entities from their repository, create an order entity etc.

Now the nature of the operands creates some interesting opportunities architecturally. At the simplest leve, instead of using repositories we might just use queries. I think this is some of the answer in the repositories vs. queries debate – it also explains why FindAll on a Repository is often seen as a smell, because we
are using to obtain a collection of catalogue data and that is not a repository concern. We might use a different strategy altogether to make these queries such as NHibernate report queries or even ADO.NET (In a previous project we created a generic DataRader for reading objects with an ID and Name, called a SmartReference that we passed a stored procedure to load our catalogue data and then loaded into picklists). The objects you deal with here will often be anaemic, exactly the kind you fear in your domain model. But that is fine here, you are not creating domain objects but the operands for the operations you will perform on the domain. Some will indeed be catalogue data for items within your domain, and you load the full object in response to the command.

We might even query against a different relational store to obtain our catalogue data. This may simply be to reduce load, but it might also be because our catalogue data might be published to this store from another application. In that case the catalogue data might well not be consistent with the current state of the publisher, if there is a delay, so our catalogue data might even be versioned.

 The important point is to realize that an application may have a healthy mix between domain data and catalogue data, and should handle each appropriately.

About Ian Cooper

Ian Cooper has over 18 years of experience delivering Microsoft platform solutions in government, healthcare, and finance. During that time he has worked for the DTi, Reuters, Sungard, Misys and Beazley delivering everything from bespoke enterpise solutions to 'shrink-wrapped' products to thousands of customers. Ian is a passionate exponent of the benefits of OO and Agile. He is test-infected and contagious. When he is not writing C# code he is also the and founder of the London .NET user group. http://www.dnug.org.uk
This entry was posted in Uncategorized. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Abdul Baruwa

    With my limited experience with NHibernate reporting queries, I’ve yet to come across an effective way to write non-fragile tests.

  • http://codebetter.com/members/Ian-Cooper/default.aspx Ian Cooper

    @Steve

    In DDD a repository is associated with an aggregate not an entity, so there may be anumber of entities loaded when we ask a repository for its contents. As you say, a dish is probably a composed object with a recipie, stcok check etc.

    As a result FindAll can load a lot of your object graph into memory. Now I can lazy-load those elements, agreed, but that may be to throw technologyat the problem uneccessarily if all I actually need is the descripton and the identifier. Just because I can get all the data back, should I?

    The key here is that I am rarely dealing with the business logic in the entity at this instance, I am just dealing with the catalogue of entities. Displaying a list of choices on the UI does not involve me in engaging with that logic.

    BTW NHIbernate provides direct support for this approach through reporting queries.

  • http://www.moneytibia.com tibia moeny

    I am glad to talk with you and you give me great help! Thanks for that,I am wonderring if I can contact you via email when I meet problems.

  • Steve Py

    I’m not sure I understand your example and why you’d think doing this with an ORM & FindAll is a smell. A dish may be associated with something like a recipe, and be included with a quantity as an order item in an order or some other construct, but a dish is just a product. (A name, price, and ID) which is derived from a base entity. (Along with other stuff like beverages etc. that have prices and names, but no association with recipes.) Irregardless, telling an ORM to fetch all dishes to display in a menu should be just fine. Even if a dish is a composed object (with a recipe, etc.) that relationship should be lazy-loaded so it’s not like we’re querying any data that isn’t necessary for the task at hand. “bulky” (and typically optional) data should be composite elements of the entity and again, lazy-loaded.

    On alternate paths where I do want all of the lazy-loaded data up-front it’s a fetch-Join operation to avoid extra hits to the DB.

    I would be concerned a bit about querying against alternate data sources for “catalogues” because then synchronization becomes an issue. Not to say there aren’t scenarios where this may be required in very large volume systems.

  • Nick

    You can’t understand fully CQ separation until you start using design by contract DBC.

    Since the pre/post/invariant conditions are made from queries, and are executed, you need CQ separation. If you have queries with side effects, you can’t use them in conditions and have code that works.

    When you do implement CQ separation, you discover your code becomes much cleaner and easier to understand.

    Initially, you will find that testing becomes easier, in particular test code is clean. ie. Assert Query. Execute command. Assert Query.

    You then realise, hey, this is just DBC in the tests.

    DBC needs to come in, and lots of testing disasppears. It’s test all the time in debug mode.

    Nick

  • http://codebetter.com/members/Ian-Cooper/default.aspx Ian Cooper

    @Rob agreed. Of course some of the ORM tools our there like NH do support projecting these dumb objects out. But I think you might be right that we hit this nail with the inappropriate entity hammer.

  • Rob

    I think this is really an area of data access that has been lost due to the recent (justifiable) hype around ORMs. The old adage “if all you have is a hammer, everything looks like a nail” seems to apply. ORMs are so nice and shiny and they auto-populate all your entities, therefore everything must be an entity! Frankly, I’ve seen this mentality even before ORMs from entity zealots (who wanted everything to be treated in domain entity form, even if they had to painfully hand-code it all).

    We are now *RE*discovering that entities are not suitable for everything, and that it’s OK to use something other than an entity in situations that merit it. What an domain entity brings to the table is a formal definition and an encapsulation of data, rules, and operations (the latter depending on the architecture). So for example, if we create a Customer entity class, that class is *the* definition of what it is to be a customer in the system, complete with rules (relationship rules, contracts, valid values, valid states, etc.). This is fine for operating on (mutating) an entity instance (operations that involve CRUD in particular). But sometimes, good UIs require display-only sets of data. This doesn’t involve CRUD at all, and doesn’t have much of an opportunity to break rules. Furthermore, the UI requirements often require mashups of data – pieces that come from different entities – to be seen together. For example, I might have a screen (report even?) that needs to show certain order header info, shipping info, customer info, and line-item summaries on the same line. It’d be rediculous to load and navigate all the entities involved to populate the screen. All we need here is a PROJECTION of the data across those different entities, not the entities themselves, and nothing handles set projections better than SQL (at least right now). There are a whole slew of situations (catalogs and lookups as you suggest here, reports, info tips, etc.) where data projections are appropriate. If your ORM can handle projections natively, all the better.