MVP Part I Sample.zip (83.87 kb)
The advantages of knowing Model-View-Presenter (MVP) pattern from scratch:
- Engineer’s knowledge can be applied across different OOP languages (like VB.NET, Ruby, Java, C#). This is advantageous for developers and architects working on different types of languages.
- Engineer’s knowledge can be applied across different versions of IDE and frameworks.
- Engineer becomes versatile and mobile across different platforms and languages.
- Engineer will not be dependent to MVP tools.
MVP Tools are not bad, the downside of using tools is that they are often tied up to IDE versions and often does not support older versions. Tools have limited support on languages and frameworks, so if the engineer is given a project that does not support his beloved tool he’ll go back to square one or worst he will blame the tool or start cursing the client/boss who gave the project… hehehe…
The goals of MVP are:
- Testability of the application
- Cohesion or separation of responsibility
Orthogonality is the ability to change the conceptual design of the application with minimal impact to the entire application. Domino effect is common to two-tier application where a slight change to data access layer affects the presentation and the business process.
Advantages of MVP:
- Parallel development. Separation of responsibilities of UI developer, business logic developer, and data access developer that make them work independently. In economics, it’s division of labor.
- Reusability. Reuse presenter in different user interface designs (web, windows form, etc). I even use it in Visual Studio Tools for Office (VSTO) application.
- Maintainability due to clear separation of responsibilities (UI, application behavior, and domain).
- User Interface independent. This is an advantage for an application that supports different user interface types.
Let’s get it on!
Download the code and launch your Visual Studio .NET and open the MVPSession.sln file.
Note: The sample is built using Visual Studio 2005 and compatible with VS 2008. If you are running Visual Studio 2003 just change the IList<T> types to IList. I already included the assemblies we need for Mocking (NMock) and Unit Testing (NUnit).
To illustrate the advantages I mentioned above, I created a sample application that will insert new employee profile. This will show how MVP will be reused and consumed by two different user interface types with minimal impact or without impact at all to the presentation logic. It will also shows how to separate the presentation from the presentation logic.
A Tester module is also added to show how to create a mock tester. Mock testing is also known as Horizontal Testing whose main goal is to test the behavior of the application without going deeply to the business logic and data access layer. We will discuss more about mocking in MVP Part II.
Figure 1 shows the architecture reference of the sample application – User Interface Layer (Presentation and Presentation Logic), Business Logic, and the Data Access Layer. In this article we will just focus only on the User Interface Layer and how to test it.
Figure 1. Sample Application Architecture
Presentation is the layer where the user interacts with the application and can be represented in many types of interfaces - mobile, web, windows forms, etc. In our sample application, we only use Windows Form and Web Form.
Presentation Logic houses the behavior or the UI logic of the view. In most cases, it requires at least a view and a model in order for the presenter to work. Service layer is sometimes optional if you don’t have data to pull from data sources (database, file, or web service). I sometimes call this the MVP layer.
Parts of the Presentation Logic:
View is best described as the logical representation of the UI and provides an interface for the presenter to communicate with the UI.
Presenter houses the behavior and UI logic.
Model is just an object that represents the module or the view. It’s an ideal place to put the validation and small business rules like computation of total amount or formulas. This just a lump of data that holds the state and data of the view. In the sample application, our model is the EmployeeModel object. In an ordering system, the model would be the Order object that contains order details and order items.
Service is a data provider and a façade that manages data retrieval from different data sources (database, web service, xml, etc). It can also house some business logic and validation. It is not aware of the user interface type (whether it is a web, mobile, or windows form). In the sample application, our service layer only returns dummy data. If you have time, you can play with it by adding the BLL and/or DAL layer.
As a rule of thumb, do not include any UI libraries in your Presentation or MVP project like System.Web or System.Windows.Forms to avoid UI objects from mixing with the presenter code. This will make your presenter less flexible.
In the diagram above you can see that Model has no direct access to Service and only the presenter has direct access to both. But it does not mean that Model cannot access the Service. In most of my application I do not give Model access to Service as much as possible to centralize all the behavior and logic in the presenter and make Model just a lump data. This makes the application easy to debug and test.
To start the implementation, let’s assume that we have four engineers – Leo, Richard, Ryan, and Chris. Leo is a Windows Form UI designer, Richard is a UI/Presentation Developer, Ryan is the backend developer, and Chris is the Architect.
Chris was given a project to create a data entry application for HR. Chris decided to design the application in MVP pattern for agile development and to let engineer work in parallel. Chris divided the project into three parts the UI Interface Layer – Business Logic Layer – Data Access Layer and distributed the task to the four engineers.
Leo as a UI designer doesn’t care about how the data will be processed or how the form will behave when Submit button is clicked. He only cares about how the data will be presented to the user and how to make the application user friendly to the users. So he created the form in Figure 2.
Figure 2. Windows Forms UI.
Richard as a Presentation developer doesn’t care about what control to use in each fields, what color of the error message and labels are, and what the UI type is, whether it is a windows forms or a web form. He only cares about the fields needed and its data type, what are the required fields, validation rules, business flow, and the service provider. So he created IEmployeeView, IEmployee and EmployeeModel, EmployeeService, and EmployeePresenter objects. See MVP project for the implementation.
Ryan as a backend developer doesn’t care about the the presentation. He only cares about how to provide the client or consumer with the data, where to fetch the data, how to connect to the database, and how to ensure the integrity and consistency of data. In our sample application we don’t have the BLL and DAL project yet, so just assume that Ryan is still working on it or probably sick. Hehehe... We hope Ryan is finished with the DAL and/or BLL by the time MVP Part II article is ready.
Question: Do Richard requires to integrate his work to the UI and backend code before he can test the behavior and flow?
Answer: No. Richard could proceed testing his work without the UI and backend. This method of testing is called Mock testing or Horizontal Testing. While Leo and Ryan are busy working on the UI and backend, Richard can proceed creating a Mock tester project to test his work. See Test project in the sample solution. In this sample we are using NMock for mock testing.
Late in the game, Marvin the Project Manager decided to add a Web form UI that will be used by the global HR in the main headquarters. So he added Jen as a resource to design HTML Forms. Jen created the form in Figure 3.
Figure 3. Web Form
Question: Are we going to create a new Presenter for the new web form UI?
Answer: No, we can reuse existing presentation with minor changes. Just take note that web is stateless so we need to modify interfaces that are statefull like the dialog boxes to display error messages.
Three months have pasts. Marvin comes in and approaches the team and says “Guys we did a great job, the project was so great that attracts another client. He likes the system and just wants to change the Salary Range dropdown to list box and wants to connect to his company database through web service.” Chris the architect evaluated and says “all we need to do is to modify the Service and the Form”. So the tasks are assigned to Leo and Richard.
Leo will just change comboxSalary to listBoxSalary in the form.
Richard will just create a new Service class that inherits the IEmployeeService and change the service used by the presenter in the Form_Load with the new service object named EmployeeWebService.
See WinUI2 project for the fixes made by leo and richard. In EmployeeWebService, I just provide a dummy data for the application to run. You can play with it with real web service if you have time.
How to Integrate Presentation to UI
Integrating presentation to UI is just three easy steps away:
1. Inherit the view interface to UI. In our example its IEmployeeView interface.
public partial class FormEmployee : Form, IEmployeeView
2. Implement all the IEmployeeView interfaces by providing code to each of the interfaces. See FormEmployee.
3. Initialize the presenter in Form_Load.
How to Run the Test Project
There are several ways and tools to run the test project.
Running Test Project Using Resharper (http://www.jetbrains.com/resharper/)
If you have Resharper you can just simply click the bubble besides the test case and select the Run From Tester context menu. This will launch the Unit Test Runner within your IDE.
Figure 4.0. Running Test using Resharper.
Figure 4.1. Unit Test Runner.
Running Test Project Using NUnit (http://www.nunit.org/)
1. Run the NUnit GUI.
2. Drag and Drop Test.dll found in Test project’s bin to NUnit GUI. You can also use the File | Open Project, and then browse the Test.dll.
3. Then click Run button.
Figure 4.3. NUnit GUI
Running Test Project using TestDriven.NET (http://www.testdriven.net/)
If you have TestDriven.NET installed you can just right click the Test project, then select the Test With from the context menu and select one of the variety of test tools supported. If you select NUnit it will launch NUnit GUI.
For a quick test you can just select the Run Test(s) from the context menu.
Figure 4.4. TestDriven.NET Context Menu
The cases above shows
- Division of labor
- Productivity and Efficiency
- Maintainability of the application
There are times when you are developing your MVP application you’ll encounter a sort of dead end where you develop a presentation that it’s hard to test. If you are in this situation just refactor your code and remember the law of cohesion. Sometimes your code gets tangled because of lack of cohesion.
May the force be with you.