The Third Object

Going from Windows Forms to WPF and Silverlight, we've seen some incredible advances in the Presentation Layer in recent years. Of course, technology advances never mean longer holidays for us developers. Instead, users just expect more. Where they might have been happy to suffer through forms-over-data user interfaces, they now expect our applications to be much more proactive in managing business processes and surfacing useful information. In short, the needs of our UI's are rapidly becoming more complicated!

When the problems we're trying to solve increase in complexity, our code has a tendency to begin to increase in complexity. But it doesn't have to be that way. Programming principles like the SOLID principles, and pattern catalogs like the Gang of Four design patterns, give us some help for managing code complexity. One of my favourite books, Domain Driven Design by Eric Evans, describes solutions for managing both complex problems as well as the code. In fact, the book's subtitle is "Tackling Complexity in the Heart of Software".

Patterns put downward pressure on code complexity

Figure: As our problem domain becomes more complicated, patterns can help to act as a downward force on code complexity.

While we've had patterns for the other layers of our code for a long time, the use of patterns on the Microsoft UI stack has become an emerging trend. A category of design patterns has evolved called Separated Presentation patterns, which describe ways to structure the code that lives in the presentation layer. The goal of this article is to give you a brief overview of the major Separated Presentation patterns, as they apply to WPF.

The three patterns I'm going to cover are Model-View-ViewModel, ViewModel-first MVVM, and Model-View-Presenter.

Plain, old-fashioned code behind

Even if you don't use a separated presentation pattern, there are two kinds of objects you'll have: Views and Models. Even in the days of .NET 1.1 Windows Forms, we were using Forms (the View) and DataSets (the Model). The separated presentation patterns, which we'll look at shortly, build on top of these.

At a minimum, we need a View and Model

Figure: at a minimum, we want to put things on the screen (a view), and we need data to put on the screen (the model)

The View is a generic name for the Window, UserControl, Control, Page, or other major UI element that encapsulates our piece of functionality. Since we intend to eventually put some kind of UI into the monitor for a human to see and interact with, any pattern needs some kind of View.

The Model is the data objects that our UI uses - for example, an Account with Transactions, which belongs to a Customer. It may be some kind of canonical understanding of the problem domain we're dealing with, used by all of our views in differently, or they might be used just by this view. They might just be Data Transfer Objects or messages returned from a Web Service/message bus, or a DataSet, NHibernate or Entity Framework classes that we fetched from a database.

The View and Model might communicate as follows:

  • Code-behind in the View can set properties or call methods on the Model
  • Controls on the View can be bound to properties on the Model
  • The Model can raise events, and the View can subscribe to them

Throughout this article I'll use dotted arrows to indicate an event being raised, and solid arrows to represent a method call or data binding.

This approach works fine, for a while, but since the only place to put code is code-behind, it can start to become hard to manage. The code to hide a button is next to the code to evaluate whether an account is overdue, which is next to the code that triggers an animation. Separated Presentation patterns allow us to clean up this code by adding a Third Object.

Introducing the Third Object

Each Separated Presentation pattern uses the View and Model. The third part of each pattern has a different name, but they solve the same purpose – any code that isn't highly UI specific, but is mostly concerned with behaviour or state management, goes there.

Introducing the third object

Figure: The Third Object is introduced by the Separated Presentation patterns. The difference between each pattern is how the Third Object communicates with the other two.

What might we expect to see in that third object?

  • Code for creating and managing background threads
  • Code for invoking a web service
  • Code for filtering an in-memory collection
  • Code for UI-calculated values that don't belong on the model
  • Code for triggering navigation to another view

So why do we have different patterns? Because there are different ways that the third object, the View and the Model can communicate. The third object always has the same responsibilities, but the way it achieves them vary.

Model-View-ViewModel

With WPF or Silverlight, MVVM is the simplest pattern to implement. The third object is the ViewModel, which the View is bound to, usually using the WPF DataContext property. The ViewModel also exposes Model objects, which the View also binds to.

MVVM

Figure: the View is bound to the ViewModel, which raises events to notify the View about changes. The ViewModel can also manipulate and subscribe to events on the Model.

For example, imagine a screen that allowed us to search through a list of patients.

  1. The ViewModel would expose a SearchText string property, which would be bound to a TextBox on the View. WPF's data binding capabilities will set the SearchText property when we type in the TextBox.
  2. The ViewModel might expose a method, or a WPF ICommand, called Search.
  3. When a button is clicked, the Search command or method on the ViewModel would be invoked.
  4. When invoked, the Search command or method would call a web service.
  5. The list of patients would be added to an ObservableCollection, which is a property exposed by the ViewModel
  6. The Patients list is also bound to a ListBox or DataGrid, which would show the new list of patients

Notice that most of our communication is done through properties, using observable collections or property changed events to notify the view that it has changed. This means the View becomes reactive to our ViewModel.

From a unit testing perspective, this is a joy, because our tests become very state-based – we can set a property, and assert the contents of another property. We don't need to test the view at all, because we can assume that data binding just works.

ViewModel-first MVVM

In regular MVVM, our ViewModel is "owned" by the View – the View is bound to and depends upon the ViewModel, but the ViewModel has no direct reference to the View. A downside to this is that if the ViewModel wants to trigger the View to do something, it has to do so through raising an event, and hoping that the View interprets it correctly.

ViewModel-first MVVM is a variation of MVVM whereby the ViewModel also holds a reference back to the view.

VM First

Figure: note that the View-ViewModel communication now uses method calls on both sides. The ViewModel knows about the View, and can call methods directly on it.

This means that the ViewModel can still use properties and events to notify the View of changes, but since it holds a reference, it can also call methods, such as Close, on the View.

Since this communication means both objects are dependent on each other, we often introduce an interface for the View. The View would implement the interface, giving it the smallest contract needed by the ViewModel. The ViewModel would be coded against the interface, rather than the implementation.

From a testing point of view, this variation is slightly harder, since once we introduce the interface we need to use a mocking or stubbing approach to provide a test implementation of each interface. We then turn from state-based testing to interaction-based testing.

Model-View-Presenter

With Model-View-Presenter, we flip MVVM on its head. Instead of the View referencing the Third Object, the Third Object references the View:

MVP

Figure: in MVP, the Presenter tells the View what to do. The View can raise events to let the presenter know something happened.

As with ViewModel-first MVVM, we use an interface for the View to provide a tighter contract between the Presenter and View.

Taking our patient search scenario again, our interaction would become:

  1. When we click Search, the view would raise a SearchRequested event, with the text from the TextBox included in the event arguments
  2. The Presenter would be subscribed to this event from the view's interface
  3. The Presenter would call the web service
  4. When the results come back, the Presenter would call a method on the view, such as ShowResults(patients), passing the results to the view.

This pattern works well for ASP.NET and Windows Forms, but since data binding in WPF or Silverlight is so powerful, it's a shame to miss out on that – MVVM does a much better job of leveraging the power of WPF. From a testing point of view, since the presenter talks to the view, we again need to use interaction-based testing and mock objects to fully test our presenter.

Testability

While the point of these patterns is to reduce the complexity of our views by separating the two major categories of code, a nice benefit we get is increased testability. With just code-behind, our only option is automated UI testing.

With the separated presentation patterns, since most of the behavioural code is in one place, we can test it without involving the view. It doesn't mean we don't do automated UI testing – I like to still have automated UI smoke tests – but it allows all of the nitty-gritty permutations to be captured as simple unit tests, keeping our automated UI test suite smaller. The ROI from testing presenters or ViewModels is so great; we may even decide automated UI testing isn't worth the hassle.

Summary

Separated Presentation patterns exist to move behavioural code out of the code-behind, so it isn't mixed up with UI technology specific concerns. The patterns may sound daunting at first, but most people are surprised by how few lines of code are needed to introduce them.

No matter which pattern you use, if any at all, you'll need the View and Model. Then it's a question of interaction patterns. I often ask clients to implement an example of both, so they can see for themselves the benefits of each.

A picture of me

Welcome, my name is Paul Stovell. I live in Brisbane and work on Octopus Deploy Octopus Deploy, an automated deployment tool for .NET applications.

Prior to founding Octopus Deploy, I worked for an investment bank in London building WPF applications, and before that I worked for Readify, an Australian .NET consulting firm. I also worked on a number of open source projects and was an active user group presenter. I was a Microsoft MVP for WPF from 2006 to 2013.

06 Sep 2010

Very nice round up of the different approaches.

Ujjaval
Ujjaval
07 Sep 2010

Hi Paul,

Nice article summarizing all different approaches.

One thing got me thinking in "Plain, old-fashioned code behind" section, you mentioned

The Model can raise events, and the View can subscribe to them
Could you give an example so that I understand what you are referring to?

Usually, in code-behind model I have seen, events are referred as UI events triggered by users and corresponding to those events, methods from Model may get executed.

U

07 Sep 2010

Hi Ujjaval,

An example might be a model object raising a property changed event. The UI might automatically subscribe to it (via data binding), or you may have some code behind that subscribes to it. Does that make sense?

Paul

07 Sep 2010

Hi Paul, pretty good article.

I have one question for example, Command as third object, with Input and Output. Input is bound to text box text property, command has Action to call web service in background thread and result set in Output property. List box is bound to Output property of Command. Do we need ViewModel, in this case?

Ujjaval
Ujjaval
08 Sep 2010

Yes, Paul, That does makes sense... I see now where you are coming from.. The kind of scenario you discuss with your Observal article. Thanks,

U

08 Sep 2010

Hi Milanche,

In that example, the command makes a pretty good third object. The issue I think you'd have is what happens when you get two commands? Or if you had two inputs (you have a TextBox that filters items in a ListBox). I find the ViewModel works as a good way of 'aggregating' these commands in to one object so they can share state.

Paul

Jack9
Jack9
08 Sep 2010

Controller->Model->(third object)->View

Third object acts as a binding layer to see if there's a need to change the view. If view changes throw new events, treat them the same as User interaction or network events, fire them off to the controller.

My problem is I find that many UIs will combine dumb and smart controls. Some things are simple, like labels/text, boxes, html controls. Some controls are (half)smart. Javascript generated controls, SWING controls, etc. In the end, adding logic to the View directly is counterproductive for anything but the smallest of projects.

A binding logic layer can be called whatever you want. I like to call it the presentation layer. My Views are as dumb as can be. A view can be manipulated and fires off events based on input/native control behavior. That's it, if possible. The presentation layer controls the affect of model changes and the view never talks to the model directly as the context of an interaction has it's own logic layer in a command (mini-controller).

While this seems very rigid and overly verbose, it is verbose but flexible. The commands can manipulate any layer directly (throw their own events), with the understanding that ANY model change generated a presentation call (which may do nothing by being a stub or not even implemented).

Model's should have NO business logic. This leaves models free to do data access and transformation which is independent from business logic and allows for replacing/changing backend sources without the rest of the app caring...standard stuff.

Other than the fact the stack can get pretty large with a lot of spend CPU time from a bunch of method calls invoking more method calls until the app finishes out it's state, it's a good general approach to prototyping for me.

Next up, namespacing all the contexts. Nobody has a good solution for that yet that I've heard and liked.

08 Sep 2010

Hi Paul,

We can use IMultiValueConverter to aggregate more outputs in one context. Or MultiBinding if you want to provide more inputs to command. On other hand we can have new third object, like collection view source. This object has input and output to, and perform server filtering for example. I think we still can have pure descriptive View in XAML and achieve reuse of elements like converter, command etc. to use on other View.

Milanche

Jiho Han
Jiho Han
29 Sep 2010

Paul,

Are you aware of a pattern called "Presenter First"?

http://www.atomicobject.com/pages/Presenter+First

Would you mind doing a comparison along with the ones you covered already? I'd like to hear your thoughts on it. Thanks for your wonderful blog!

Jiho