views:

54

answers:

1

If I don't want to expose the internal state of my Domain Objects, but I need to display them, I can think of three approaches. Which of these is the most "correct" (if any?).

  1. The "DTO/ViewModel approach". This seems to be a popular approach in the ASP.NET MVC world (especially with the use of AutoMapper).
  2. The "decorator approach". If I have a "Customer" entity, I decorate it with a "DisplayableCustomer" who can access the internal state of the customer (in most languages that I've dealt with).
  3. The "interface approach". Where I do something like this:

    class Customer {
        ....
        public void renderWith(CustomerRenderer renderer) {
             renderer.renderCustomer(address,name);
        } 
    }
    
    
    interface CustomerRenderer {
        public void renderCustomer(Address address, Name name);
    }
    
+1  A: 

I vote for, and widely use, your #1 option. Several reasons why:

  • Allows for complex view models, like combining multiple lists of my domain objects. Think a PostViewModel with a Post element and an IList container hanging off of it.
  • On my current project, we have abstracted the domain validation to where it bubbles up into our custom ViewModels, and do some slick Ajax-validation on forms.
  • While the concept doesn't directly expose your domain objects on the Model, I have no problem hanging Post off of a property of my PostViewModel.

The last point is why the ViewModels concept really exists. It's no violation of DDD to expose your Domain object all the way up to your UI or even the view - this is by designed and expected of DDD and UI concepts. You only expose objects from your domain to use, and lock in/persist their states with services and infrastructure. So, you are in no violation of using the actual Domain object in your UI.

It's when you involve MVC concepts for your UI, and trying to render that specific View of a page/location. You may (and will) have additional display elements that may not be related to the Domain at all, like a Progress Bar that is only for the UI. A progress bar is a concern only for the UI and APplication layer. It has nothing to do with your domain.

So, the DDD solution I accept is to use a hybird object in the Application/UI layers that can hold a number of objects: both Domain objects and Application objects to render for that one specific View. This is the concept of a ViewModel, at its core reason of being.

The ViewModel concept can be thought of as your Application Layer non-business objects in DDD terms.


Going off topic a little and talking about one specific technology, ASP.NET MVC has additional features to help make this concept work together nicely. It's not directly built into ASP.NET MVC, but is available as an additional assembly from Microsoft called the Futures project.

Check out my blog post about a couple of features, the single most useful feature is the RenderAction extension method:

http://eduncan911.com/blog/html-renderaction-for-asp-net-mvc-1-0.aspx

This is an extremely powerful concept that spins up the underlying controller and calls the action method. Doing this greatly simplified our ViewModels to only care about the View they are rendering. I no longer have to attach things like sidebar controls or other common data boxes, navbars, etc that have nothing to do with the View.

RenderAction is different then RenderPartial for pure DDD reasons: It lets you move the business logic back into a Controller, where it belongs. And the controller calls the proper view to render it's display. This strictly follows both DDD and MVC concepts.

Microsoft has stated that RenderAction will be part of ASP.NET MVC 2.0 when it is released next year.

Sorry for the rant...

eduncan911
RenderAction seems very similar to the Action View Helper in Zend Framework (http://framework.zend.com/manual/en/zend.view.helpers.html#zend.view.helpers.initial.action) for PHP. But the framework maintainers advise not using it since it basically goes through the whole MVC cycle again, inducing unneeded overhead. Does RenderAction have these same failings, or is it designed differently so that it doesn't?
blockhead
Yes, it is similar to Action View which is advised against in Ruby (as you found out). But in Asp.Net Mvc, it is very efficient as the output is inserted into the Output TextStream. That is the advantage of Asp.Net Mvc over Asp.Net WebForms (old method). WebForms required spinning up the entire page life cycle, where Mvc does not rely on the page life cycle for rendering an action method on a controller class file.
eduncan911