In this article we will understand MVP, execute a sample project with MVP, implement the same using windows UI and then finally we will discuss about the differences between MVP and MVC.
This article assumes that you know MVC. In case not than you can read about the same at http://www.c-sharpcorner.com/UploadFile/shivprasadk/12346712242008055033AM/123467.aspx
The simple stock project
The best ways to understand any architectural concept is by taking a small practical sample and then apply fundamentals on the same. So let's first discuss a simple scenario and then let's think how MVP fits in to the same. Below is a pictorial representation of a simple stock project. We can increase the stock value and decrease the stock value. Depending on the stock can have three status overstocked, under stocked or optimally stocked.
We have three scenarios depending on which the UI will change color.
Stock value |
Color |
Value is in between 1 and 5 ( Optimally stocked) |
Green color |
Value is above 5 ( Over Stock) |
Blue color |
Value is less than zero ( Under stocked) |
Red color |
What we will do is define the problem logic in two parts:-
-
Presentation logic
-
Business logic
Business logic will be handled by business object |
Presentation Logic will ne handled in the ASPX or windows form |
Receive the events from the presentation and maintain the stock value accordingly. In short increment and decrement the stock value. |
Trigger the events increment stock and decrement stock. The events will be triggered when the user clicks the increase stock button or the decrement stock button. |
Depending on the value of the stock determine the three states under stocked, overstocked or optimally stocked. |
Depending the state of the stock change the visual colors :-
- Under stocked change to RED.
- Over stocked change to blue.
- Optimally stocked change to green
|
The other responsibilities look fine let's concentrate on the last responsibility which we have marked in red color where the UI needs to change colors depending on the stock value. This kind of logic in presentation is termed as presentation logic.
If you look from a generic perspective the work responsibilities allocated to the business object and the user interface look fine. There is slight concern when we look at the presentation logic.
We have three big problems:-
Reuse of presentation logic
If we want to reuse the presentation logic in some other UI type like windows. I mean to say we have implemented this logic in ASP.NET web pages and we want to reuse the same in windows. As we have the presentation logic is tied up in the UI code it will be difficult to decouple the same from the UI. We also would like to use the same presentation logic with other pages of same types.
Presentation is tied up with the business object
The presentation is tied up with the business object. It's doing lot of work checking the stock status using the business object and changing the UI colors accordingly.
UI testing
If we want to test the user interfaces it becomes difficult as the UI is highly coupled with the UI. It becomes difficult to test these parts as different pieces.
So let's take the above three problems and see how we can solve it. MVP will help us solve the above three problems.
Problem 1:- Reuse of presentation logic
If we want to reuse the presentation logic irrespective of the UI type we need to move this logic to some separate class. MVP does the same thing. It introduces something called as the presenter in which the presentation logic is centralized.
Note: - In this scenario the presentation logic is simple. In real projects you will find the presentation logic complex and there is lot of bandwidth of reuse in other user interfaces.
Problem 2:- Presentation is tied up with the business object
To decouple the presentation from the business object we introduce an interface for every UI. The presenter always talks through the interface and the concrete UI i.e. the web page communicates also through the view interface. In this way the model is never in touch with the concrete UI i.e. the ASPX or windows interface. All user interface should implement this interface so that the presenter can communicate with the UI in a decoupled manner.
Problem 3 will get solved if we solve the first two problems.
The View Interface and presenter of the stock project
We will first visualize how the UI will look like. There will be two buttons one which increments the stock value and the other which decrements the stock value. The stock value is displayed on the stock text box and the color is set according to the value of the stock.
All events are first sent to the presenter. So all the events needs to connect to some methods on the presenter. All data needed by the UI i.e. in this instance we need the stock value and the color should be defined in the interface so that presenter can communicate using the same.
So below is the interface for the ASPX page. We need the stock value so we have defined a method called as 'setStockValue' and we also need the color so we have defined a method called as 'setColor'.
public interface StockView
{
void setStockValue(int intStockValue);
void setColor(System.Drawing.Color objColor);
}
The presenter class will aggregate the view class. We have defined an 'Add' method which takes the view object. This view will set when the ASP.NET page starts.
public class clsPresenter
{
StockView iObjStockView;
public void add(StockView ObjStockView)
{
iObjStockView = ObjStockView;
}
.....
.....
.....
}
When the user presses the increase stock button it will call the 'increasestock' method of 'clsPresenter' and when the decrease stock button is called it will call the 'decreasestock' method of the 'clsPresenter' class. Once it increments or decrements the value it passes the value to the UI through the interface.
public void increaseStock()
{
Stock.IncrementStock();
iObjStockView.setStockValue(Stock.intStockValue);
ChangeColor();
}
public void decreaseStock()
{
Stock.DecrementStock();
iObjStockView.setStockValue(Stock.intStockValue);
ChangeColor();
}
We had also talked about moving the presentation logic in the presenter. So we have defined the 'ChangeColor' method which takes the status from the 'Stock' object and communicates through the view to the ASPX page.
public void ChangeColor()
{
if (Stock.getStatus() == -1)
{
iObjStockView.setColor(Color.Red);
}
else if (Stock.getStatus() == 1)
{
iObjStockView.setColor(Color.Blue);
}
else
{
iObjStockView.setColor(Color.Green);
}
}
Now let's understand how the UI will look like. The UI either it's an ASPX or windows should inherit from the stock view interface which we have previously explained. In the page load we have passed the reference of this page object to the presenter. This is necessary so that the presenter can call back and update data which he has received from the model.
public partial class DisplayStock : System.Web.UI.Page,StockView
{
private clsPresenter objPresenter = new clsPresenter();
protected void Page_Load(object sender, EventArgs e)
{
objPresenter.add(this);
}
.....
.....
.....
}
As we have inherited from an interface we also need to implement the method. So we have implemented the 'setStockValue' and the 'setColor' method. Note that these methods will be called by the presenter. In both the buttons we have called the 'increaseStock' and 'DecreaseStock' method of the presenter.
public partial class DisplayStock : System.Web.UI.Page, StockView
{
private clsPresenter objPresenter = new clsPresenter();
protected void Page_Load(object sender, EventArgs e)
{
objPresenter.add(this);
}
public void setStockValue(int intStockValue)
{
txtStockValue.Text = intStockValue.ToString();
}
public void setColor(System.Drawing.Color objColor)
{
txtStockValue.BackColor = objColor;
}
protected void btnIncreaseStock_Click(object sender, EventArgs e)
{
objPresenter.increaseStock();
}
protected void btnDecreaseStock_Click(object sender, EventArgs e)
{
objPresenter.decreaseStock();
}
}
The model is pretty simple. It just increments and decrements the stock value through the two methods 'IncrementStock' and 'DecrementStock'. It also has a 'getStatus' function which tells what is the stock level type i.e. over stocked, under stocked or optimally stocked. For simplicity we have defined the stock value as a static object.
public class Stock
{
public static int intStockValue;
public static void IncrementStock()
{
intStockValue++;
}
public static void DecrementStock()
{
intStockValue--;
}
public static int getStatus()
{
// if less than zero then -1
// if more than 5 then 1
// if in between 0
if (intStockValue > 5)
{
return 1;
}
else if (intStockValue < 0)
{
return -1;
}
else
{
return 0;
}
}
}
The complete flow for the stock project
Below is a complete flow of the stock project from MVP perspective. The UI first hits the presenter. So all the events emitted from the UI will first route to the presenter. Presenter will use the model and then communicate back through the interface view. This interface view is the same interface by which your UI will inherit.
We have solved all the three problems with all the actions passing through the presenter the ASPX / Windows is completely decouple from the model. The presenter centralized the presentation logic and communicates through the interface. As the presentation logic is in a call we can reuse the logic.
As all the commands are passing through the presenter the UI is decoupled from the model. Now that we have all the components decoupled we can test the UI component separately using the presenter.
To just show how magical the presenter is. I have reused the same presentation logic in a windows application.
In the below sample we have ported the same presenter logic in a windows application.
private void Form1_Load(object sender, EventArgs e)
{
objpresenter.add(this);
}
private void btnInCreaseStock_Click(object sender, EventArgs e)
{
objpresenter.increaseStock();
}
private void btnDecreaseStock_Click(object sender, EventArgs e)
{
objpresenter.decreaseStock();
}
#region StockView Members
public void setStockValue(int intStockValue)
{
txtStockValue.Text = intStockValue.ToString();
}
public void setColor(Color objColor)
{
txtStockValue.BackColor = objColor;
}
You can understand the difference of how consuming the model objects directly and using a presenter varies. When we use the presenter we have moved the UI presentation logic to the presenter and also decoupled the model from the view.
Below is the code in which the UI directly uses the model...Lot of work right.
With presenter all the presentation logic is now centralized
The above figure summarizes the difference between MVP and MVC. We have just summarized the figure in tabular format below.
MVP |
MVC |
In MVP the view and the model is completely decoupled. |
In MVC the view and model is not completely decoupled. |
In MVP presenter handles all the UI events |
In MVC the views handles the events |
In MVP the presenter calls back to update the view via the view interface. |
In MVC the controller passes the model to the view and the view then updates itself. |
The project is coded from three aspects :-
-
Using simple UI and Model perspective.
-
Implementing MVP using WEB.
-
Implementing MVP using windows.
The Web and windows samples are shown to show how we can reuse the presentation logic.
It would selfish to say that all the above knowledge is mine. Below are some link which I have referred while I was writing this article.
Alex on MVP VS MVC http://ameleta.spaces.live.com/blog/cns!5F6316345A821420!163.entry
Martin flower GUI architectures http://martinfowler.com/eaaDev/uiArchs.html
Mr Nikola http://blog.vuscode.com/malovicn/archive/2007/12/18/model-view-presenter-mvp-vs-model-view-controller-mvc.aspx
Microsoft thoughts on MVP http://msdn.microsoft.com/en-us/magazine/cc188690.aspx
Billy on MVP http://www.codeproject.com/KB/architecture/ModelViewPresenter.aspx
TDD http://haacked.com/archive/2006/08/09/ASP.NETSupervisingControllerModelViewPresenterFromSchematicToUnitTestsToCode.aspx
WIKo http://c2.com/cgi/wiki?ModelViewPresenter