Tuesday, November 20, 2007

Domain Presentation View

Was just reading a blog entry from Ray Houston on his view classes. The scary thing is we have exactly the same approach, right down to the naming of the classes!

In our case if we had a Customer aggregate and we were displaying lists of Customers in a grid then loading each instance of the aggregate would be deeply inefficient. We'd be loading lots of data/rules that we didn't need and we'd also be missing information that we needed to display in the grid because that information would come from other aggregates. We might thus end up navigating associations from one aggregate to another just to get simple primitive data types to display in the grid, which is wildly inefficient.

What we really needed for these situations were fast loading read-only classes that have information from one or more aggregates but that only load the information/behavior needed for the display in the grid. Enter our Info objects.

We have Info objects (ClientInfo) and InfoLoaders (ClientInfoLoader). The loaders only have retrieval methods and are not repositories. The Info classes are then mapped to database views.

We actually have the Info objects in another assembly called Presentation, but we do have a reference from the Presentation to the domain assembly so that the Presentation classes can use things like Services/Rules/Specifications/Enums and so on. We could remove this dependency if we needed to, but it would be a little bit of effort and so far I don't see it as a major issue.

So far we only have a few Info objects, certainly not one per aggregate. We also don't create one Info object for each view (as in an MVP view) so its possible that when you load an Info object you get data that you don't need. If this became an issue we could deal with it.

Anyway I shouldn't have bothered explaining it as Ray has already done a good job. I also believe there is a discussion of this sort of thing on the DDD newsgroup (don't have link), but it is heartening to know we are not the only people using this approach.

Share This - Digg It Save to del.icio.us Stumble It! Kick It DZone

2 comments:

  1. Scott Millett12:00 pm

    Hi Colin I just saw this blog entry and have a question. I too need to show information on a cross section of entities or reporting needs but don't really want to load the entire object graph. I like your idea, but would you create a separate assembly for your InfoLoader or would you include this in your repository implementation?
    e.g. MyCompany.MyApp.Persistence would contain the concrete repositories and the concrete InfoLoaders?

    If you could show me how you set up your projects or point me in the right direction it would be very much appreciated.

    Thanks Scott
    (scott (at) elbandit.co.uk)

    ReplyDelete
  2. Hi Scott,

    I don't have the codebase handy as I've moved companies but we ended up putting the InfoLoaders and the related presentation classes in one project completely seperate from the domain. This ensured we only added one project.

    You could also consider using namespaces to define the boundaries, so keeping the domain, repositories, the info loaders and the presentation view in one project and using namespaces :

    http://codebetter.com/blogs/jeremy.miller/archive/2008/09/30/separate-assemblies-loose-coupling.aspx

    Only really works if you also use a tool like NDepend and I've not done more than play with that approach.

    Ta,

    Colin

    ReplyDelete