Putting the M in MVC – Part III

Monday, April 6, 2009

In the last post we talked about using entities as the models in an MVC application. This approach works well until an application reaches a certain level of complexity, at which point entities as the M in MVC can become painful.

I believe entities exist to serve the business layer. They also have a role in the data access layer, but only because the data access layer has to be acutely aware of entities. The reverse is not true – entities don’t need to know details about the data access layer nor how they are saved in persistent storage. Entities aren’t owned by the UI, or the data access layer. Entities are business objects and are owned by the business layer.

An application that supports a complex business needs a fine-tuned layer of business logic. You know an application is growing in complexity when you uncover scenarios like these:

  • Validation rules go beyond mere database constraints - maximum discount is 10% unless an administrator is overriding the discount percentage
  • Multiple sets of validation policies are in effect - contracts signed in the state of Maryland after Jan 1, 2009 require additional checks to meet regional law #443570.
  • Entities are involved in long running business processes - the request for proposal requires approval from three directors before moving to a published state.
  • The application integrates with external applications and services - changes to any customer information must be published to the CRM system within 10 minutes.

These types of requirements have a significant impact on the design and behavior of the business layer and its entities. You want all this complicated business stuff in a layer where it is testable, maintainable, and free from the influence of all the infrastructure that surrounds it – databases, data grids, message queues, communication protocols, and the technology du jour. It’s a business layer built with business objects that encapsulate business state and business behavior. It’s the secret sauce that makes money for your company. It’s a rich model of your domain.

So - why wouldn’t we want to use this rich domain model inside of our views? Isn’t it every young view’s dream to grow up and marry an extraordinarily rich, fat model?

Models, Models Everywhere

Views can grow complex just as quickly as business logic can grow complex. Complex views might exhibit some of the following conditions.

  • Displays aggregate information from across the application (reporting views).
  • Displays information from disparate sources (composite views).
  • Lives on a different tier (the view is built using JavaScript, JSON, and client-side data binding).

Perhaps you don’t consider these views as super-complex because you build them all the time, but the types of views we are talking about in the above three bullet points do place requirements and constraints on the model. For example, the UI may require a model that can serialize into a JSON or RSS format.

If you share your entities or domain model with the UI layer, you’ll find your business objects have to serve two masters. The requirements from these two masters will pull your business objects in different directions, and they won’t be optimized to fit in either role.

Also, ask yourself these questions about the model for your views:

  1. Who determines what properties the model should have?
  2. Who invokes business logic on the the model?
  3. Who owns the model?

Answers:

  1. The view.
  2. Not the view.
  3. The view.

Complex applications often require multiple models. There is the domain model that encapsulates your company’s secret money-making business sauce, and then there are multiple view models that the UI layer consumes. Somewhere in between is logic that maps data between the various models. This isn’t a new idea, and it was at one time known as the Model Model View Controller pattern.

You might create a model class for each type of view, like a – MovieReviewViewModel, and perhaps all the UI models derive from a base class. The model classes will hold just the state that their respective views require. These classes don’t need behavior – they are essentially just data transfer objects. In a sense, the model classes also become contracts that explicitly describe what the controller needs to put together for the UI, and the view author sees a model with just the information they need.

Of course, building these additional models comes with a price.

  • You have to map data from the domain model into view model classes, and vice versa.
  • You have to figure out how to provide validation logic for view models.
  • You’ll write more code, and manage more classes.

It’s up to you to decide if the benefits are worth the price:

  • Your entities and business objects are optimized for business logic
  • Your view models are optimized for the UI
  • You achieve separation and isolation of the business and UI concerns 

What Was The Original Question?

It was:

“I have created domain entities like Customer, Order, etc. They come out of  repository classes backed by NHibernate. I’m wondering if I send them directly to the view or if I create a ViewModel class to hold data. I’m confused by all the terminology”.

I haven’t given a definitive answer, but I hope I’ve given you enough of my opinion to see that the answer depends on the complexity of your application and its long term goals. For forms-over-data applications, passing your entities can be a simple and effective solution. For more complex applications you may need models built specifically for your views to maintain the integrity and maintainability of your business objects.


Comments
Yazid Monday, April 6, 2009
Excellent article,

I have used the MVC/MVP in a normal ASP.NET and it works like a charm and everything is testable. In this new ASP.NET MVC I would also create a ViewData (ViewModel) that holds data only. In addition, I would have a the VIewData part of the Model and Controller.

Yaz
Scott Monday, April 6, 2009
In my limited experience with MVC, I've always leaned toward passing POCO objects being passed to the View. But my current project isn't backed by a database per-se, but by a service layer. The main reason we've been using POCO, IMO, is because we're using the Webforms view engine and it's almost completely untestable. By keeping the controllers as thin as possible and the views/view models as dumb as possible, we seem to be reducing the amount of testing of the views.
scott Monday, April 6, 2009
@Scott +1 !
@Yaz - Didn't quite get what you mean by "have the ViewData part of the Model and Controller".
laimis Tuesday, April 7, 2009
An excellent description and especially rather well put reasoning why you would need a separate model for the view and business logic.

Yazid Tuesday, April 7, 2009
Scott,

Sorry I was not that clear, what I meant is:

The View Implements an IView
The IView has a property that holds the ViewData (contains data only, this is what I would call an entity)

The fact that the IView passes itself to the controller and thus ViewData is part of the controller.

The controller can pass the ViewData to the Model and and hence the ViewData is part of the Model. I think this I am not entirely right because the Model may expect a type that is of a different of the ViewData. Hence I will have a dataMapper in between the controller and the Model.

Regards
Yaz

gravatar Rick Strahl Friday, November 20, 2009
The arguments for direct binding and explicit ViewModel are pretty dried and clear - thanks for putting them into this series nice and concise.

Where I run into problems is when to use which and whether it's 'acceptable' to mix and match in a single application (which is what I've been doing). The problem is that many forms in applications are practically straight maps to the data model, while other forms required complex display formatting for which a ViewModel is clearly better.

It just seems excessive both in terms of overhead and code bloat to *always* opt for a ViewModel, so I've tended to mix and match. Yet it feels slightly inconsistent to have different approaches in different forms.
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!