MVP is an important presentation pattern that the bold success of frameworks such ASP.NET MVC for the Web, and WPF for the desktop, is overshadowing a bit too much. MVP can be successfully applied to a variety of application models including ASP.NET, Windows Forms, WPF and Silverlight. And, more importantly, it really allows you to reuse any chunks of the presentation logic that is not directly bound to the technicalities of a given platform.
From here, it stems out that MVP is the ideal pattern of choice for building multiple front-ends for the same application. A Web form and a Windows form that behave in the same way, and show the same data, may not have the same appearance, but they will likely share the same presentation logic. In SaaS scenarios, where the vendor makes the same application available to a variety of customers through the Internet, a thorough application of the MVP pattern greatly simplifies the management of user interface while it fully reuses any presentation logic.
In MVP, the presenter is nerve centre of the presentation layer. Regardless of the different name, the presenter is just a sort of controller that, triggered from the view, operates against the middle tier and pumps fresh data into the view. In doing so, it only uses the contract explicitly exposed by the view object itself.
Let’s explore more in depth the structure of an MVP presenter and the set of features it typically offers in the real world.
The Presenter and the Service Layer
According to the popular Martin Fowler’s bestseller “Patterns of Enterprise Application Architecture”, the service layer pattern refers to a set of methods that offer a common programming interface over any service and data object that lives in the middle tier and must be invoked from the client. In a nutshell, the service layer allows you to script the domain objects, and any workflows, and application services you may have in the back end. The service layer represents the application logic and is opposed to the domain logic.
Most of the time, if you implement the Service Layer pattern, then the presenter will gain a reference to one of the macro-services in the layer and invoke methods. Here’s the typical structure of a presenter method bound to some action triggered from the view.
As you can see, the service layer is just a way to abstract the business logic for the sake of presentation. If you don’t have a service layer, then the presenter would deal directly with the business logic and any public object (be it a service, workflow, or data context) exposed out of that.
What’s the Model?
Originally, both MVC and MVP were formulated to help dealing with the complexity deriving from monolithic applications. The separation of concerns these patterns touted had to be intended as the separation of the code base in logical layers such as presentation, business and data. Today, we think of MVP for applications already devised in multiple layers. The presentation layer is where we try to fit MVP or other similar patterns. What does it mean?
The view and presenter are easy to identify. The view is the user interface shown to the user. For example, in an ASP.NET-based presentation the view is the ASPX markup plus the code-behind class. The presenter, instead, is a separate class consumed by the event handlers from within the code-behind class.
What’s the model, instead?
As I see things, the model is of secondary importance in an MVP scenario compared to view and presenter. The model is not something new to add to the system just because you’re applying the MVP pattern. The model refers to something that is already a fundamental part of the system. At the end of the day, the model is the public interface of the middle tier. In a multi-tier application, the entry-point to the model is represented by the service layer interface (if you implement the related pattern) or, more simply and directly, by the public interface of the domain model. If you use an O/RM tool to support and persist the domain model than the entry-point to the model is represented by data context interface of the O/RM of choice. Otherwise, it is the interface you craft yourself for your domain model.
To exemplify, if you use LINQ-to-SQL then the entry-point to the model is represented by the DataContext object. Similarly, if you opted for Entity Framework, it will be the xxxEntities class you obtain from the Visual Studio 2008 wizard. Finally, if you went for, say, NHibernate it will be the Session object.
Selecting the Next View
In addition to refreshing the view, the presenter is also responsible for implementing any navigation logic within the application. In particular, the presenter is responsible for enabling (or disabling) sub-views in the current view and for commanding navigation to the next view when appropriate.
A sub-view is essentially a subset of the view and may be like a panel that can be expanded or collapsed as required. The presenter controls sub-views through members (mostly Boolean members) on the view interface.
What about transferring control to another view and, why not, another presenter?
You start with a static class that represents the application controller—that is the central console that holds all the logic to determine the next view. The application controller is the centralized point for handling screen navigation and the flow of an application. Figure 1 shows how it works.
Here’s some sample code that illustrates the behavior of the application controller.
The ApplicationController class represents the shell that presenters invoke to navigate elsewhere. As you can see, the NavigateTo method invokes an external component the implements the navigation workflow. The navigation workflow is any class that implements a given interface—in this case the custom INavigationWorkflow interface.
NavigateTo method takes two arguments—the name of the view and an argument to further specify the selected view. The ApplicationController class lives in the same assembly as presenters and view interfaces and is shared across UI platforms.
How would you initialize the application controller and register the navigation workflow? For ASP.NET applications, this occurs in global.asax. For Windows applications, the actual navigation component is instantiated and registered in the startup program:
The actual navigation workflow class—the MyAppNavigationWorkflow class in the example—contains the workflow to move to a given view. The class implements the INavigationWorkflow interface. The internal implementation of the navigation workflow can be as sophisticated as a Windows Workflow Foundation program or as simple as a long switch statement, as in the code below:
The MyAppNavigationWorkflow class holds references to all possible forms in the application and switches to the right one as appropriate given the current run time conditions. The example above is created with Windows Forms in mind; in an ASP.NET world, you would use
Response.Redirect to move to a different page or, maybe, load a user control to update an existing view.
As mentioned, this is not the only possible approach to implementing an application controller. Another possibility entails that you set up a workflow—for example, using Windows Workflow Foundation (WF)—and go through the workflow to determine the next view. In terms of design, instead, an application controller approach—regardless of the implementation details—is beneficial because it doesn’t create dependencies between views.
It is also important to note that the navigation controller depends on the navigation workflow only through an interface—which makes it possible for you to decide at run time which workflow to load using a plug-in model or, better yet, dependency injection.
An application controller is the machinery that decides about the next view based on some input, like the view name (as in our example) or just a collection of values that denote a state of the view. If you have a large application with hundred views, the application controller that takes care of all possible transitions for all views may become a quite complex one. For this reason, you might want to split the navigation logic across multiple controllers at the granularity that you feel works best for you.
You can even devise a scenario where you have an application controller per use-case, if the use-cases to implement involve several views and complex navigation sequences. Needless to say, in a front-end with multiple navigation controllers, each presenter must receive a reference to its navigation controller upon instantiation.
The presenter component, in the end, is a key element of the presentation layer. And the name just reflects that.
Dino Esposito is one of the world's authorities on Web technology and software architecture. Dino published an array of books, most of which are considered state-of-the-art in their respective areas. His most recent books are “Microsoft ® .NET: Architecting Applications for the Enterprise” and “...
This author has published 54 articles on DotNetSlackers. View other articles or the complete profile here.
Other articles in this category
Introduction to StructureMap
Have you heard of StructureMap, generally know what it’s for, and want to know how to get started qu...
DI Patterns: Constructor Injection
In this article, an excerpt from the book "Dependency Injection in .NET", we will take a detailed lo...
The Command Pattern
In this article I will provide a quick refresher on what the command pattern is used for, how it wor...
Brian Mains discusses how to implement the Arrange-Act-Assert pattern in TypeMock.
Key Process Patterns
This article, based on chapter 2 of Specification by Example, presents effective patterns for softwa...
Please login to rate or to leave a comment.