MVP in Action

Back in August-September 2007 the concept of the MVP (Model-View-Presenter) pattern had finally 'clicked' with me, since attending Ron Jacobs' session at TechEd 2007 and reading related literature online. Since then I have had quite a bit more exposure to it, half of it being with my own personal projects.

I have to say there is nothing better when learning about a pattern than to try it out and develop it from something that doesn't work well and is cumbersome to maintain, to something more logical, cohesive and easy to follow.

MVP - also the name of a shoe shop in Hong Kong

Here's a recap of MVP and where it has evolved from, based on my understanding and experience:

Now that we've seen (at a high level) what MVP is and where it came from, let's tackle the questions of how it can be implemented.

Getting The Ball Rolling

Think about what happens when the application starts - a Model has to be initialised, the View created with its UI controls, and the Presenter linking the two together. By the time the UI is displayed, it should reflect the initial state of the Model, so there's one partial ordering needed: Model before (displaying) View. The application startup sits outside this 'triad', though the UI technology used will usually determine how this will be defined (e.g. in App.xaml[.cs], or Program.cs).

Here is the approach I took in HexCell (not the Officially Mandated way of doing it):

  1. Application creates the main window (View), but does not display it.
  2. Application creates the main Presenter, passing the main View as a reference to an interface.
  3. Main Presenter creates the Model in its constructor and holds a reference to it (since it is purely in-memory, so no interface abstraction necessary - unless you wish to test the Presenter in isolation with mock View and Model).
  4. Main Presenter binds events / sets delegates as necessary for interaction between the View and Model.
  5. Main Presener calls the View to display itself in its initial state.

If the Model has components that would be abstracted behind an interface (e.g. database access), the first three steps would be as follows:

  1. Application creates the main window (View), but does not display it.
  2. Application creates the relevant Model components.
  3. Application creates the main Presenter, passing the main View and relevant Model components as references to their corresponding interfaces.

Handling Multiple MVP 'Triads'

As applications become more complex, the interface becomes composed of several components that have different areas of responsibility, therefore one Presenter and View is not enough to handle the diverse functionality. Hence, some literature talks of constructing MVP "triads". In my view, a way to make this practical is to think of these triads as similar in concept to mini-applications hosted within one large host application. Keep in mind that these triads do not necessarily map 1:1 to each composite control within a window, in a way that a button doesn't need its own MVP triad.

Dealing with multiple triads makes things a little trickier, but here are some principles I followed when structuring the application:

So far, these principles have guided the architecture of my after-hours project and seem to be working out. A good example of this in action is the changing of the language of the entire application from within the Settings View. When the setting is applied, the Settings Presenter calls the Main Presenter, which changes the current interface language in the Model (and loads the corresponding UI text). This change causes an event to be raised, which allows another component to refresh its View with the updated language data (since this UI text is applied programmatically, instead of using WPF data binding).