This is the continuation of my last Blog about MVC. I will introduce MVP (Model-View-Presenter) and try to explain how it differs from MVC (Model-View-Controller).
There was a concept called MVP in an IBM / Taligent paper of 1996. It unfolded a refined MVC, consisting of more than just three parts, although the main triangle was still the same. The difference was that this concept allowed views to live on client-side while the model was on the server side, the controller being on both sides. In between the controller and the model were "Selection" (selected model items) and "Command" (undoable mementos), in between the controller and the view was "Interactor" (menu and button actions).
Then Martin Fowler used the term MVP for his advanced concept of MVC, but later gave it up in favour of PassiveView, SupervisingController and PresentationModel.
The main difference in Fowler's diagram was that the direct connection between model and view was given up. So there was no more triangle, instead the presenter was a mediator between model and view. And this is a concept that you see everywhere in today's user interface implementations.
I would say this shines through simplicity. Everyone that knew about the complexity of integrating MVC especially in context of web applications could accept that idea.
The general responsibilities of model, view and presenter (controller) do not change very much from MVC to MVP. It's more the way how they work together.
The model is not allowed to know the presenter.
The presenter will change model properties, and the presenter will render them in the view. Thus a model change listener mechanism does not make sense any more. MVP models do not fire change-events.
Also the structure of the model is different. It needs not to provide every model item or property separately. The presenter will read domain objects or data-transfer-objects from the model, and provide them to the view in its own way. The responsibility of the model is more to read from and write to the business layer, provide the data in a use-case specific way, and sometimes cache them.
The view is not allowed to know the presenter.
The view should contain absolutely no presentation logic. Not even enabling a field when some checkbox gets activated. Like a baby that can not do and understand anything it will simply fire any user action as event to the presenter that listens to its cries :-)
Two interfaces make up an MVP view:
addViewListener()
, property value getters and setters like getXXX()
and setXXX(value)
, and methods to enable or disable fields. Important is that only the view is allowed to import the windowing system. When you use e.g. Swing as windowing system, the presenter is not allowed to import any Swing class, nor is the model. Just the view binds itself to a system that may be replaced some years later. That way you keep the replacement effort minimal.
But the biggest advantage of keeping out the windowing-system of presenter and model is that you can mock the view for unit-testing your MVP!
Again the most complex of the three. The presenter implements the view's listener interface. It holds a reference to the view-interface to be able to manipulate it, and registers itself as listener to the view at construction time. The presenter also holds a reference to the model.
One part of the presenter is data-binding. It is recommendable to implement it in a separate class, encapsulating the model-view relation. Responsibility is to populate all view fields with model properties on load, and to read back all view fields into model properties on save.
Optionally this can be implemented as two-way binding, that means a model property change would change the according view field, and a view field change would modify the according model property. (You're right, this sounds recursive, to be avoided by the programmer.)
The presenter itself uses the data-binding whenever needed, but it keeps out of the mapping-dependency between model and view. It mediates between view and model by listening to view events and doing according model changes. It also performs data-validation. Finally it needs to manage business layer errors thrown by the model. These must be presented to the user in an acceptable way.
One disadvantage of the MVP concept is that the presenter is kind of God Class. For example, when no two-way binding has been used, mistakes in data-mapping may not be detected as early as in MVC, where the relation between model and view is event-driven and thus reliable.
Imagine I wrongly mapped the firstName UI field to thelastName
model property. When I now change the firstName field, an MVC would write this tolastName
property, and the model would fire an event against the view, which would write the new first name into the lastName UI field. You would see that mistake immediately when testing.
In MVP, the presenter would also write the firstName UI field to thelastName
property on "Save". But when it would not refresh the view then, you could not see the mistake on the UI, because it is not bound directly to the model!
Another disadvantage of MVP is the fact that you can not connect several view / controller couples to one model, because the model listener mechanism is missing. Such would be possible only if the data-binding is implemented as listener mechanism. It is really important to keep the binding separate from the presenter.
My next Blog will be about refinements concerning MVP. And I am working on a good Java code example.
ɔ⃝ Fritz Ritzberger, 2017-02-06