I’m playing around with the Model View Presenter (MVP) design pattern for use in a new project. At first I found it a little strange – we’ve been toying with the use of the Microsoft Smart Client Factory (MSCF) which makes use of MVP; however, the project I’m on won’t be using the MSCF – so I went about implementing my own version of it.
At first I found it a little unusual – however, I’ve now gotten my head around the main issues with it (such as confusing it with the Model View Controller pattern) and am happily using it. One thing I find strange is that the MSCF classes seem to suggest that your Presenter is in the same physical assembly as your View – I always thought that the whole point is to abstract the two apart from one another, hence allowing you to replace the View with another one. You can of course still do this in the MSCF implementation, but I couldn’t understand why they’ve somewhat coupled the two together by putting them in the same assembly.
Another thing that’s confused me. Who’s responsibility is it to control navigation between one view/presenter and another one e.g. your first View has a button on it, and on clicking this you want to navigate to a new view. In your first View, should you do something like this?
// On click event MyChildForm Child = new MyChildForm ();
I don’t like this approach, because you’ve got business-level logic in your View i.e. controlling navigation to another part of the system. What if you had some complex business logic there? I suppose you could have a method on the View’s interface like "LaunchChildWindow()" which would get called by the Presenter, and move the business logic into there like so:
// In View private void ButtonClickHandler (object sender, EventArgs e)
#region Implementation of IView
public void ShowChildFormA ()
ChildFormA MyForm = new ChildFormA ();
public void ShowChildFormB ()
ChildFormB MyForm = new ChildFormB ();
#endregion // In Presenter public void DetermineNavigation ()
if // bla View.ShowChildFormA (); else View.ShowChildFormB (); }
However, I’m still not convinced about such an approach, and so thought about the Command pattern.
Bear in mind that my Presenters are in another assembly to my View, and therefore can’t reference the View assembly (circular reference). So what I ended up doing what implementing a set of Commands. These live in a third assembly and have a reference to my Views assembly and can leave those Views as required. They implement an ICommand interface that is defined in my Presenter assembly. So depending on some business logic, a Presenter may launch a Command as required. The Command may spawn another Presenter/View combination off, or it may create some business logic class etc.
The only issue I have with this approach is where my business logic sits – some are in the Commands, some in the Presenters. I think I’ll end up making presenters even for non-visual commands (or some other classes) so that all my business logic is in one place – plus they shouldn’t sit with the Command tier as that currently is closely coupled to my UI layer.