Dolphin Model-View-Presenter
The Dolphin Model-View-Presenter (MVP) schema is an evolution of
the Application Model approach. Although it is derived from the Taligent/IBM
strategy with the same name, we will examine Dolphin first as it is simpler to
describe within the concepts we already introduced. The Dolphin strategy is
also the one most often referred as “Model View Presenter” without additional
clarification. To add to the nomenclature, Fowler identifies the Presenter
with the more appropriate “Supervising Controller”.
As we introduced in the Application Model section, the main purpose of this
Model is to hold visual state, acting as an intermediate between the Domain
Model and the View/Controller pair. The Application Model was a model in every
respect in terms of design: it performs notifications, remains oblivious of
its listeners, is directly accessed by the View and modified by the Controller.
Yet, due to the strictly specific nature of the visual state, it would be
convenient if the Application Model could handle visual logic and refer to the
View directly, like the Controller does, while still keeping and handling View
state.
Let’s analyze the Controller: with widgets of modern GUI toolkits handling
low-level events (e.g. physical keyboard presses), the controller has only the
duty of modifying the models according to higher level events (e.g. textlabel
content modified). These events are then transformed by Controller logic in
actual Model changes, some of which may have an impact on the visual state,
which is stored in the Application Model. It seems like a good idea to have an
Application Model containing this visual state if the assumption is that this
state (e.g. a field being red) is shared among Views. Once again, this state
is almost never shared and mostly tied to a specific View.
Summing up, the roundabout mechanism the Controller uses to take care
of purely visual state would be considerably simplified if we define
a new role, the Presenter, which combines the Application Model and the
Controller in a single entity.
Like the Application Model, the Presenter:
- holds visual state, and keeps it synchronized against changes in the
Domain Model - converts business rules (e.g. engine rpm number too high)
into visual representation (e.g. label becomes red) - eventually handles state for selection, and application of actions
to the subset of the Model specified by this selection.
and like the Controller, the Presenter:
- it is tightly coupled to the View
- refers to the View directly, and can act on it to alter its
visual aspect. - handles events forwarded by the View, converting them into action through proper logic.
- modifies the Domain Model, which contains no visual state
- handles View logic according to the View state it contains
The Domain Model is a strict domain model and is unchanged, and is still accessed by the View for data
extraction and from the Presenter for data modification. The View
is an aggregation of widget, fetches data directly from the Domain Model, instead of having to rely
on the Application Model as a forwarder. The View behavior is now hybrid
Active/Passive, fetching Domain data directly from the Domain Model but with
visual aspects applied by the Presenter (Passive) directly acting on the
widgets. A variant with a fully Passive View is possible, and is known as
Presenter First.
If the user changes the content of a widget, the presenter is informed, it fetches the value
from the widget, and acts on the model. The model is listened to by the view, which updates
itself accordingly, and by the presenter itself, which now sets the color.
The view may manipulate its own logic and aspect internally if it does not need to modify the
model.
every view has a specific presenter. There’s a strict relationship between the two
Each triad is independent and does not know about the other ones. in general,
if the triads must coordinate each other, they can rely on an “application
model”. When the application Model for a given triad is requested to perform a
change, it signals its intention to an application coordinator. This
coordinator can eventually decide to create a new triad, if needed.
FIXME: Add Picture
FIXME: reformulate in general
FIXME: Write something about data transfer objects as a transferring entity of data between the
model and the presenter. It is possible to add a service layer between the
model and the presenter that is responsible for packing the data from the model
into a DTO that the presenter then uses to set the view’s contents.
FIXME: The application model approach assumes that there are multiple View/Controllers acting on the
same application model, but in practice it’s very rare that an application model is generic enough
to be applicable to multiple views or controllers, exactly because its state is designed to satisfy
the visual needs of a specific View.
FIXME: Add the fact that the controller is talking to the view as a generic object that generates
events. This allows easy repleaceability of the view, not only with a mock, but also with a different
renderer. As long as it generates the same events and responds to the same interface. this may seem
trivial, but if the difference in interface is large, this replaceability is not achievable.
FIXME: Division of functionality in the presenter must keep into account if the functionality would make
the presenter grow too much and act as a data bottleneck. Sometimes if the logic is complex and the view is
intrinsically complex, it pays off to let this logic live in the View and have a simple presenter.
FIXME: In a large application, a presenter normally handles only one view, but it could
handle multiple views if they are closely related.
FIXME: Communication choices.
1) View holds reference to the Presenter. View invokes directly methods on the presenter, instead of sending events. or
2) View emits events. Presenter listens
Presenter holds a reference to the View. directly invokes its methods.
In the original MVC, the controller was mainly responsible for handling user events.
in MVP, the Presenter is responsible for handling Model changes.
Composed of supervising controller, passive view.
Moves presentation logic from the Model (as in aplication model) to the presenter.
MVC vs. MVP:
- Controller in MVC: main objective is to handle user events. Model modification is a consequence of it.
With smart widgets, user events are handled by the widgets, and then forwarded to the controller.
MVP: Presenter main objetive is updating the model, and keeping the visual state (as in application model)
handling events passed by the view is a consequence of it.
The presenter can be instantiated either by the client code, or directly by the
view. If this is the case, the View must know the model, so that it can
instantiate the Presenter and pass both the model and itself to it.
Concerning callability on sone side or the other (e.g. event vs. method call)
write that the view has two ways to interact with the controller and forward
events: strong coupling through direct invocation, or loose coupling through raising
events at a higher semantic level.
forwarding is done depends on the degree of coupling you allow between the View
and the Presenter. If the view must invoke directly a Presenter’s method,
obviously it must know its interface, so it must hold a reference to it and
know its interface. The alternative is that the view is oblivious to who is
listening, and just broadcasts events (commands) to report the button press.
The presenter observes these events and take appropriate action when triggered.
As you can see, the difference is subtle, and apparently irrelevant, but it can
be useful depending on the degree of coupling and self-containment of the view
vs. the controller (Presenter)