Lets say you are working in ASP.NET MVC 2 (or your favorite MVC web framework). Lets also say you have a nice rich model. Your controllers have to fetch the model objects and get that data to your view. How do you do that?
There are a bunch of ways:
- Pass the model directly to the view
- Create a "View-Model" class and put a property on it that exposes the model
- Create a "View-Model" that completely hides the model behind properties of its own
And there are a bunch of variations on those too. But those are the main options.
The best thing about #1 is it's as simple as can be.
#2 is almost as simple as #1 but adds the ability for you to create other custom properties on the "View-Model" object that can perform various operations for the view. For example, you might format values, or retrieve the latest object from a list, etc.
The downside to these two options is your View is directly coupled to your Model. This might become a problem if you end up with lots of Views that depend on the same Model, or if the Model keeps evolving and being refactored over time.
That's where #3 comes in. By creating all new properties on the View-Model, you're basically applying the Dependency Inversion Principle and saying, "This view needs this data, I don't care where it comes from as long as someone provides it." You will now need some form of mapping layer to get the data from the Model to the properties of the View-Model. This is more work, but it's also nice. When the Model changes, you only need to update the mapping, which is dramatically easier than digging into lots of HTML and finding what could be many references to your properties.
Now, that said, there are still lots of changes that will require you to make changes to the Model, View-Model, and View. Any change that is a change in the *meaning* of the Model will cascade this way. But there is a whole set of changes that won't cause this update cascade. Like any refactoring of the Model for example.
The obvious downside with #3 is more code and more work (Though tools like AutoMapper certainly help).
So, how do you know when to apply which pattern? Is one pattern always better than the others, or does it depend. And if it depends, on what? And how do you know when it's time to switch from one to the other?