Tuesday, August 23, 2005

MVP concept

Newsgroups: microsoft.public.dotnet.languages.csharp
From: "Joanna Carter \(TeamB\)"
Date: Thu, 14 Apr 2005 09:48:42 +0100
Local: Thurs, Apr 14 2005 4:48 pm
Subject: Re: Document/View Model - Advice Sought!

As Jeff has indicated, this kind of relationship cannot be resolved when you only have a Model and a View.

This is why someone came up with the concept of MVC (Model View Controller) and later with MVP (Model View Presenter), a more sophisticated and flexible version of MVC

In MVC, the Controller acts as a Mediator between the Model and the View and can ensure that, if a message comes from the View, that the resultant action invoked on the Model does not cause infinite recursion.

MVP takes things further by splitting out the responsibilities for handling changes even better.

I have had extensive practice in implementing an MVP framework using Delphi which adds a couple more ideas to keep things better encapsulated than the MVC.

The Model, not only holds an instance of the Value Type (the object to be editied), but it also holds a Current Selection and a Command Set. Instead of relying on a UI to maintain a selection, the Model is notified via an Interactor when a user makes a Gesture in the UI; the Current Selection can vary from being a sub-list in the case of a multi-item object to just the single object in the case of a basic ValueType like a string or integer.

When the Selection changes, the Command Set is notified and changes itself to only allow Commands that are viable for the given Selection. In the case of a list of objects, if the Selection is empty, then the Add Command is enabled but the Insert, Delete, Edit, Cut and Copy Commands are disabled. Changing the Selection to a single item will enable all Commands, while a multiple selection will disable Edit and Insert.

The Command Set can be visualised in the UI by a popup context menu or maybe a MS Money style 'what to do' bar.

The View is made to be an Observer of the Value Type held in the Model and will respond to changes in the Value Type by updating itself to reflect the current state of the object it is displaying.

The Presenter, which holds a reference to each of the Model and View, also holds one or more Interactors.

An Interactor is essentially an object that has one or more event handlers or delegates that are listening for changes in the UI (View). The Interactor responds to a Gesture, by interpreting it into : a change in the Selection or a sending of change of content in the edit to the Value Type. This includes UI elements like radio groups or checkboxes that are used to represent sets or boolean values

UI elements like buttons and menu items are not usually handled by an Interactor, but are linked directly to a relevant Command; the OnClick event handled directly in the associated Command and the button or menu item enabled or disabled according to the state of the Command.

Now comes the bit that keeps the Model and View apart in terms of stopping recursion.

Interactors can be enabled or disabled; they can enable or disable themselves. Which means that if they instigate a change in the Value Type that is known to propogate to a change in the UI, the Interactor can prevent itself from receiving further notifications until the change has completed.

Interactors can also be nested and can propogate user input to other, more sophisticated, Interactors to handle things like dragging an item from one control to another or even to another application.

Ultimately, the MVP framework allows for the nesting of MVP 'Components' so that each property of an object has its own MVP to link it to an edit/checkbox/combo on a form and these are all contained and maintained within an overall Presenter which links the object in the Model to the form.

Once the nested MVP framework is completed, it is then possible to write a business class and design a form where each edit has the name of the property it is to represent, but where there is absolutely no code on the form itself. Then by simply instantiating a Presenter, passing the business object to the constructor, a Model will be created for you, a View (form) will be created for you, they will be linked together, all the properties will have MVPs created for them and linked to the controls on the form via Interactors; and finally the form will be shown and managed by the Presenter.

Regardless of whether you want to achieve this level of sophistication in your current situation, you at least need to implement some kind of Controller to act as a Mediator between your Model and View, taking into account the idea of enabling and disabling used in my Interactor classes.

If you are interested in further reading on MVP, then I have some articles on my website www.carterconsulting.org.uk, or you can Google in the news groups for "joanna carter interactor" for more discussion on the finer points on this part of the MVP which are not covered in the articles.

Joanna
--
Joanna Carter
Consultant Software Engineer

Newsgroups: borland.public.delphi.oodesign
From: "Joanna Carter \(TeamB\)"
Date: Fri, 4 Feb 2005 12:51:32 -0000
Local: Fri, Feb 4 2005 8:51 pm
Subject: Re: Best way to model this?

The real difference between MVC and MVP is that the 'message flow' is handled via two different 'channels', one for each direction.

The user makes a Gesture in the View

An Interactor responds to that Gesture (that Interactor may delegate reponsibility to nested Interactors, dependent on the complexity of the Gesture).

If that Gesture is intended to alter the visual selection in the View, the Interactor notifies the Selection in the Model.

Changes to the Selection are observed by the View and the visualisation is updated to match.

The Selection then notifies any Observers, one of which will be the View which will update itself accordingly, the other is the Command Set.

The Command Set updates itself based on the Selection to accomodate things like Commands not being available when more than one/only one item are/is selected.

Assuming that the Selection is now up to date, the Interactor translates subsequent Gestures, determines which Command on the Model is to be called and calls this Command.

Commands can be undone and redone and can also support the concept of a history if required.

If executing the Command raises an exception, then the Interactor is responsible for creating a Presenter for that exception and directing the UI to a suitable focus point.

Assuming the Command succeeds, the Model, which contains the Value Type, passes the change to the Value Type.

The Value Type responds to the change by notifying any Observers, one of which would be the View.

This structure is more flexible, in that Interactors and Commands can be relatively freely substituted depending on the nature of either the View or the Model.

MVPs can also be nested, so you get a MVP 'component' for a BO, the View of which will be a form, but this component will contain other MVP components, one for each of the properties of the BO, the views of which will be the edits on the form.

The inner MVP components can be created at runtime based on the names of the BO properties matching the 'PropertyName' of the relevant edit on the form.

I tend to talk about creating Presenters for Value Types; this then means that your client code usually creates/retrieves a Value Type (a BO is a composite Value Type) and then simply passes that Value Type to the constructor of a Presenter. The Presenter is responsible for creating a form or other display and will self-destruct when the form closes.



Comments: Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?