Putting the M in MVC – Part II

Thursday, April 2, 2009

Rob just put the M into MVC using Subsonic and a Subsonic MVC Template. The template allows you to go from 0 to functioning application in less time than it takes to listen to a Rob Zombie song. Fantastic work by Rob C, and it leads nicely into the actual question behind this series of posts:

“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”.

This is a difficult question to answer without looking at the specifics of an application, but what follows is my opinion on the matter.

Entities, Models, Ownership

To me, an entity is a business object that is full of data and behavior. The data probably comes from a database. The behavior comes from code you write to implement “business logic”. Perhaps the business logic is simple validation code, or perhaps the business logic is code that talks to other entities and objects in your business layer to coordinate more complex business goals – like placing an order and running a long business process.

An entity exists to serve the business layer. If the customer asks you to change how the order total displays, you’ll make the change in the UI and not touch any entities. But, if the customer asks you to change how the order total is calculated, you’ll make the change in the business logic and possibly modify the Order entity itself. Since the entity exists to serve the business layer you should assume the business layer owns all entities.

Sharing

It is reasonable to share these business layer owned entities with the UI layer in many applications. This is what happens if you use Rob’s templates. Here is an excerpt from a template generated controller:

// GET: /Movie/Edit/5
public ActionResult Edit(int id)
{
    var item = _repository.GetByKey(id);
    return View(item);
}

//
// POST: /Movie/Edit/5
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Edit(Movie item)
{
    if (ModelState.IsValid)
    {
        string resultMessage = "";
        try
        {
            _repository.Update(item);
            resultMessage = item.DescriptorValue() + " updated!";
        }
        // ...
    }
}

Entities come out of repositories and go directly into a view. During a save operation, the entities materialize from the view and go to a repository. The approach is simple to understand, and works well if you can picture your software like the following:

 entities, views, logic

The entities are round pegs, while the business logic and views are round holes. There is no friction because the entities fit the needs of both layers perfectly. What you are building in these scenarios is a “forms-over-data” application. These types of applications usually have the following characteristics:

  • Every input on a view maps directly to an entity property.
  • Every entity property maps directly to a column in a database table.
  • The majority of the business logic is validation logic.
  • The validation logic mostly exists to satisfy database constraints (like field lengths and null-ability)

I’m not trying to make “forms-over-data” applications sound trivial or stupid. If all you need is a data entry application then you don't want to add unnecessary complexity to your software. Share entities with the UI views and keep things simple. Simple works well.

In the next post we’ll talk about when to avoid sharing entities with your UI layer. As you might guess, it will involve a diagram like this:

 mismatch


Comments
Comments are now closed.
by K. Scott Allen K.Scott Allen
My Pluralsight Courses
The Podcast!