Choose MVP over MVVM

When I first saw the Model-View-ViewModel pattern, I thought it was pretty cool. I actually wrote an entire framework and an application using the MVVM pattern. It works, and it gives you a nice separation of concerns between your Model and the rest of your application.

What’s never sat well with me is the amount of redundant and sometimes boilerplate code you have to write in your ViewModel. Assuming you have POCO objects in your domain model and that your domain model shouldn’t know anything about your ViewModel (it shouldn’t), then if you have a domain class called Customer with a Name property, chances are you’ll have a ViewModel class called Customer, with a property called Name, except that the ViewModel will implement INotifyPropertyChanged, etc. It works, but once you get down to coding, it’s a LOT of extra work.

There is an alternative out there called Model-View-Presenter. Most people claim that MVVM is a form of MVP, but once you look closely, that’s not the case (or at least, that’s now how people are using MVVM). In both MVP and MVVM architecture, the ViewModel/Presenter forms a separation between the View and Model. The difference is that in MVVM, the ViewModel works with Model objects explicitly, but in MVP both the View and the Model are abstracted services to the Presenter. Perhaps it’s clearer with an example:

class CustomerViewModel
{
    Customer wrappedCustomerModel;
    public CustomerViewModel(Customer customerToWrap)
    {
        wrappedCustomerModel = customerToWrap;
    }
    
    // Leaving out the INotifyPropertyChanged stuff
    public string Name 
    { get { return wrappedCustomerModel.Name; } }
}

class Presenter
{
    public Presenter(IView view, IModel model)
    {
        populateViewWithModelData(view, model);
        view.UserActionEvent +=
            new UserActionEventHandler((s, e) =>
            {
                model.ProcessAction(e.Action);
                populateViewWithModelData(view, model);
            });
    }
    private void populateViewWithModelData(
        IView view, IModel model)
    {
        // custom mapping logic here
    }
}

There’s at least one major benefit to the Presenter class over the ViewModel class: you can wrap the model.ProcessAction class in a try...catch block and catch all unhandled exceptions from the Model logic in one place, logging them, and notifying the user is a nice friendly way. In the ViewModel case, any property getter can throw an exception, which causes lots of problems in WPF, not the least of which is that it sometimes breaks the binding and no further updates get sent back and forth.

Now let’s look at the constructor of the Presenter again:

    public Presenter(IView view, IModel model)

Nothing says that the View the presenter is hooking into couldn’t be a ViewModel:

    public Presenter(IViewModel viewModel, IModel model)

If you do this, then the Presenter separates the ViewModel from the Model! Ok, does that sound like too much architecture? Why did we want a ViewModel in the first place? We wanted it because we wanted to make the GUI logic testable, and then use WPF’s binding mechanisms to do a really simple mapping of View (screen controls) to ViewModel (regular objects). You still get that advantage. You can create a ViewModel that implements INotifyPropertyChanged and fires off an event when one of its properties changes, but it can just be a dumb ViewModel. It becomes a “Model of the View”, which is what the ViewModel is supposed to be. Since the ViewModel then has no dependencies on the Model, you can easily instantiate mock ViewModel objects in Expression Blend and pump all the test data you want into them.

Doesn’t that mean we’ve shifted the problem from the ViewModel to the Presenter? The Presenter obviously has to know the mapping between the Model and the ViewModel. Does that mean it reads the Customer Name from the Model and writes it into the Customer Name property in the ViewModel? What have we gained?

What if the Presenter was smart? Let’s assume that IModel represents that state of some domain process the user is executing. Maybe it has a Save method, maybe an Abort method. Perhaps it has a property called CustomerAddress of type Address. Maybe it has a read-only property of type DiscountModel, an Enum. Even though we’re working against an abstract IModel interface which probably doesn’t include all of the concrete public properties and methods, we have the power of reflection to inspect the actual Model object.

What if the presenter actually generated a new AddressViewModel and populated it with data from the Model any time it saw a public property of type Address on the concrete Model object? What if it hooked up listener events, or passed in a callback to the AddressViewModel so it could be notified when the user modified the address, and it would write those changes back to the Model, then inspect the Model for changes and update the ViewModel with the results? What if when it saw an Enum property on the Model, it automatically generated a DropDownListViewModel? What if, when it sees a Save method, it generates a SaveViewModel that gets mapped to a button in the View?

Can we write a generic Presenter that can comprehend our Model and ViewModel objects? Can it even build the ViewModel for us, based on what the concrete Model object looks like, and perhaps based on some hints in a builder object that we pass in?

The answer to all these questions are “Yes.” We can use the Presenter to automate the generation of the ViewModel layer based on the look & feel of the domain model itself. I leave this as an exercise for the reader…

2 thoughts on “Choose MVP over MVVM

  1. Mike Brown

    Scott,
    You’re the second person I’ve seen recommend an MVPVM (Model View Presenter ViewModel) approach.

    Two things to comment here.

    First, I wouldn’t necessarily suggest that you have a ViewModel for every Entity in your domain, but rather a view model for every Feature.

    For example, if you have a feature Add a Customer, you don’t need a customer viewmodel, the UI can bind directly to the Customer object itself. (BTW it’s considered rude to throw exceptions from properties, use a method instead.)

    Your AddCustomerViewModel would provide the customer as a property (and the UI can bind to Customer.Name, Customer.Email and so forth). You only need to add INotifyPropertyChanged when the UI needs to be notified of external changes to a property and when you’re creating an object, no one else is going to change it right?

    Second, I’ve been pursuing the concept of Dynamic Viewmodels as well. I’m following the route of using Metadata to define the viewmodels (attributes on the model or purely data driven services). I’ll document the approach in my upcoming book.

    I don’t think that adding a separate presenter into the mix is necessary. Because when you boil it down, MVVM IS really just a variant of MVP (which Fowler separated into Supervising Controller and Passive View). A lot of the confusion and rejection of MVVM I have seen has come from people not fully understanding the pattern.

  2. Scott Whitlock Post author

    Mike,

    I may not have the nomenclature of Presenter right (there is always the Presentation form too, right?) but the idea stands on it’s own. I have implemented something similar to this (without all the talk of reflection). Basically here’s how it works:

    I define an abstraction for a “business task” in my model. This roughly correlates to a screen or page in a desktop or web application. I also allow tasks to have subtasks, etc.

    Part of the contract of a business task is that you can query it for all of the things you can do to it (I call them “task operators”, but that’s only due to my own background in industrial controls, where buttons, etc., on an electrical panel are called operators).

    So when you run the app, it starts with some main task. The presenter gets this main task, and has to “build” a ViewModel for the task. It delegates this to a ViewModel building service. There is a default builder that can generally render any kind of task (with any kinds of operators) into some kind of ViewModel that will at least display. Now in order to inject more information into the process of building a ViewModel, each task also has a separate class associated with it called a ViewModelBuilder. This builder is just a declarative list of hints that customizes the building of the ViewModel. For instance, one of my task operators is called ChooseOne (chooses one thing from a list of things). Normally this gets rendered to a ViewModel that ultimately would get rendered as a drop down box, but I can use a ViewModel Redirector in my builder for a given task and tell it to apply a ViewModel that would render as a grid with some given columns instead. I also apply icons to buttons in this way, and I specify where ViewModels should be laid out (docked in the bottom left, or along the top, etc.).

    This is working, and the nice thing is that the View and ViewModel classes have zero domain knowledge in them. I would never have an AddCustomerViewModel, but I would have an AddCustomerTask, and an AddCustomerViewModelBuilder.

    The AddCustomerTask uses a declarative syntax, like EditValue(this, x => x.CustomerFirstName); That one line creates my task operator for editing the customer first name and hooks up all the plumbing for actually populating the task operator state and setting the property when it changes. I can also specify an action to execute when it changes like this: EditValue(this, x => x.CustomerFirstName, () => whenItChangesDoThis());

    The AddCustomerTaskViewModelBuilder also uses a declarative syntax and only specifies minimal layout and ViewModel widget selection logic.

    I assure you, it’s working well.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.