OdeToCode IC Logo

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.