View-Presenter

Problem

A page in a Web application contains controls to display application domain data. A user can modify the data and submit the changes. The page retrieves the domain data, handles user events, alters other controls on the page in response to the events, and submits the changed domain data. Writing this code in the Web page (the code-behind class) makes the class complex and difficult to test. In addition, it is difficult to share code between Web pages that require the same behavior.

Forces

  • You want to maximize the code that can be tested with automation. (Views are hard to test.)
  • You want the share code between pages that require the same behavior.

Solution

Separate the responsibilities for the visual display and the event handling behavior into different classes, the view and the presenter. The view class (the Web page) manages the controls on the page, and it forwards events to a presenter class. The presenter contains the logic to respond to the events, and in turn, manipulates the state of the view.
LogicalView_ViewPresenterPattern.png
Figure 1
Logical view of the View-Presenter pattern.

Interaction with the Model

The interaction with the model is handled exclusively by the presenter; the view is not aware of changes in the model. When the model changes, the presenter updates the view to reflect the changes.
You can implement the interaction with the model in several ways. For example, you can implement the Observer pattern, and have the presenter listen to events of the model and update the view as required. Another approach is to use an application controller to update the model. For more information about the Application Controller pattern, see Application Controller pattern.

Testing the Presenter

When you implement the View-Presenter pattern, you can test the presenter independently of a view implementation. You can perform this testing by replacing views with mock implementations.
If the presenter references its view implementation class, the view implementation class is required to run the presenter’s unit tests. To enable you to easily test your presenter, you can define an interface for the view, and replace the view implementation reference with a reference to the view interface. This means you can easily create a mock implementation of your view for your presenter’s unit tests, and those tests will not require the real view implementation.
For example, the following code shows a mock view that allows you to test that the Customer property is set.

internal class MockSummaryView : ISummaryView
{
    private Customer _customer;

    #region ISummaryView Members

    public Customer Customer
    {
        get { return _customer; }
        set { _customer = value; }
    }

    #endregion
} 

With this mock implementation, you can easily create automated tests for your presenter. The following code illustrates the kind of unit test code you can create.

[TestMethod]
public void OnViewLoadedCallsControllerCurrentCustomerAndViewSetCustomer()
{
    MockSummaryView view = new MockSummaryView();
    MockCustomersController controller = new MockCustomersController();
    controller.InnerCurrentCustomer = new Customer();
    SummaryViewPresenter presenter = new SummaryViewPresenter(view, controller);

    presenter.OnViewLoaded();

    Assert.IsNotNull(view.Customer);
    Assert.AreSame(controller.CurrentCustomer, view.Customer);
} 

Liabilities

  • There are more solution elements to manage.
  • You need a way to create and connect views and presenters.
  • The model is not aware of the presenter. Therefore, if the model is changed by any component other than the presenter, the presenter must be notified. Typically, notification is implemented with events.

Related Patterns

  • Application Controller. You can make presenters interact with an application controller to avoid adding page flow and screen navigation logic to presenters and, therefore, making it easier to update the page flow.

Last edited Nov 20, 2007 at 12:25 PM by ejadib, version 4

Comments

No comments yet.