7

Relatively new to patterns, let me straight away show an example in the context of WinForms.

I have a basic MVP Passive View structure, which one should I go ahead with:

public partial class UserView : Form, IUserView
{
    public event EventHandler Save;

    public UserView()
    {
        InitializeComponent();

        new UserPresenter(new UserModel(), this);
    }
}

public class UserPresenter
{
    public UserPresenter(IUser model, IUserView view)
    {
        view.Save += (sender, e) => model.Save();
    }
}

or

public partial class UserView : Form, IUserView
{
    public event EventHandler Save;

    public UserView()
    {
        InitializeComponent();

        new UserPresenter(this);
    }
}

public class UserPresenter
{
    public UserPresenter(IUserView view)
    {
        var model = new UserModel();
        //assuming I have the logic to bind property values from View to Model
        view.Save += (sender, e) => model.Save();
    }
}

My questions are:

1) Who should know of the concrete instance of model User, View or Presenter?

2) What will be the benefit in that case?

3) Suppose my Model is never dependent on the View. In that case what's wrong if View knows Model? After all UserView is made to present UserModel isn't it?

4) If Presenter should interact with only interfaces of Model and View, then to call model.Save in Save eventhandler, where do I get the concrete instance of Model from?

There are two duplicate questions here and here, but they aren't exactly dealing with my scenario I guess..

Community
  • 1
  • 1
nawfal
  • 70,104
  • 56
  • 326
  • 368

4 Answers4

17

Strictly speaking, you should have the following rules:

  1. Model does not know the View or the Presenter.
  2. View does not know the Model or the Presenter.
  3. Presenter knows both Models and Views, but only through their interfaces.

The Presenter coordinates all communication between the Model and the View, typically by handling events that are raised by the View. So to answer your questions:

1) Who should know of the concrete instance of model User, View or Presenter?

Ideally, neither. The Presenter should be communicating with UserModel through an IUserModel interface. The concrete instance is injected into the Presenter (e.g. through its constructor).

2) What will be the benefit in that case?

The primary benefit is for automated unit testing. You can inject mock Models or Views to test units in isolation.

3) Suppose my Model is never dependent on the View. In that case what's wrong if View knows Model? After all UserView is made to present UserModel isn't it?

There's nothing inherently wrong with it. There are variations of MVP that support direct communication from the View to the Model, typically to take advantage of data binding. You lose some testability in exchange for not having to write the binding code from scratch.

4) If Presenter should interact with only interfaces of Model and View, then to call model.Save in Save eventhandler, where do I get the concrete instance of Model from?

Depedency injection, such as the simplified example shown below.

public class SamplePresenter
{
     public SamplePresenter(ISampleModel model, ISampleView view)
     {
          view.Saved += (sender, e) => model.Save();
     }
}

public interface ISampleModel
{
     void Save();
}

public interface ISampleView
{
     void Show();
     event EventHandler Saved;
}

public class Program
{
     [STAThread]
     static void Main()
     {
          ISampleModel model = new SampleModel();
          ISampleView view = new SampleView();
          SamplePresenter presenter = new SamplePresenter(model, view);
          view.Show();
     }
}
Bob
  • 171
  • 2
  • 1
    `The concrete instance is injected into the Presenter (e.g. through its constructor).` from where? From the `View` right? As in my first example isn't it? In that case can you say `View` doesnt know of the `Model`? – nawfal Jan 18 '13 at 19:17
  • 2
    Something external to the MVP triad. In the example above, I just did so in the Main method. You may consider using some kind of IoC container. – Bob Jan 18 '13 at 19:23
  • Thanks, let me search for IoC container examples, never used it. – nawfal Jan 18 '13 at 19:27
  • What would u suggest, shouldn't view and presenter be in separate projects (so that changing view becomes easier)? – nawfal Jan 18 '13 at 19:32
  • I put the View interfaces in the same project as the Models and Presenters. The concrete implementations of the Views should be in a separate project. – Bob Jan 18 '13 at 19:46
  • yes thats exactly what I meant. Having View interfaces outside presenter makes no sense. But I keep model a separate project as well – nawfal Jan 18 '13 at 19:48
  • I see you've wired the save event in Presenter's constructor. Shouldn't there be line of code to unregister the Save event ? I believe that might lead to memory leak. Correct me if I am wrong, I also believe that Presenter should implement Disposable pattern and that is where the event should be unregister. Let me know your thoughts. – Josh Feb 15 '13 at 02:42
  • @Josh that was a silly example in my code, just to avoid writing a dedicated `Save` method. Ideally it should not be in constructor. – nawfal Jan 11 '15 at 14:07
7

What's wrong if view knows model? After all UserView is made specifically for UserModel isnt it?

Nothing. It's accepted practice in the Supervising Controller variant of the MVP pattern. The view interacts directly with the model for simple operations while more complex operations are marshalled throught the presenter. While in Passive View, everything goes through the presenter.

Additionally, see Jeremy Miller's Build your own CAB series to get a better idea on the differences between the two approaches: Supervising Controller and Passive View.

Big Daddy
  • 5,160
  • 5
  • 46
  • 76
  • Sorry to unselect.. A question, shouldn't view and presenter be in separate projects (so that changing view becomes easier)? – nawfal Jan 18 '13 at 19:33
  • @nawfal...No problem. Having it in separate projects it a good idea. For example, suppose your requirements changed from Winforms to Webforms? No problem, then. – Big Daddy Jan 18 '13 at 19:38
  • @nawfal...The benefits are in your face when the requirements change. – Big Daddy Jan 18 '13 at 19:45
  • can you suggest a possibility where having presenter and view in one project helps? – nawfal Jan 18 '13 at 19:49
  • 2
    @nawfal: Having presenter and view in one project still allows you to unit test the presenter independently of the view which is the whole point of MVP. The view interfaces and presenters should be organized in folders anyway so refactoring out to a separate project when needed (e.g. changing view engines) wouldn't be that difficult. One reason to do separate projects from the start is that it's easier to keep your references clean so that you don't start using view-specific code (e.g. `System.Web`) in your presenters. – Nelson Rothermel Apr 21 '15 at 22:28
3

The Presenter should know about the Model, the View should not. A presententation layer is a good idea in many user interface applications. A presentation layer is simply an adapter. It presents an interface that's easy for a user interface layer to use (i.e., it presents lots of events, bindable properties, and so on) while obscuring the underlying data layer. This makes the data layer easier to re-use.

EDIT

So why can't the view just talk to the model directly? It certainly can. The problem is that there is usually an impedence mismatch between the model and the view. In other words, the programming interface that's natural for the view to use does not match the interface that's natural for the model to expose. If you adapt the model to suit the view's needs, then you end up creating a strong coupling between the model and the particular type of interface you're using.

For example, your app might be a GUI app today, but what if tomorrow you're asked to produce a version for the cloud? The events and bindable properties that are helpful for Winforms will just get in the way when you try to switch to WCF Rest. If you use a presentation layer, then adapting your code to the new environment will be much easier.

Peter Ruderman
  • 12,241
  • 1
  • 36
  • 58
  • But why is it wrong if view knows about model? If model knows view, its a disaster I can understand, but why can't view know model? After all `UserView` is made specifically for `UserModel` isnt it?I will update my question. – nawfal Jan 17 '13 at 19:40
  • `If you adapt the model to suit the view's needs, then you end up creating a strong coupling between the model and the particular type of interface you're using.` No that's not something I will be doing at all. My model is hard baked and I will never let view decide it. Model stands for itself. Now what's wrong if view comes to know about such a model? – nawfal Jan 17 '13 at 19:54
  • I wouldn't go so far as to call it wrong. It simply creates a coupling between the view and the model. The point of all these patterns is to facilitate change. You spend more effort up front in the hopes that it will pay off when you're asked to fix bugs and add features. If your model truly is "hard baked", then it's less of a concern. But my experience in this business suggests that "hard baked" interfaces are rare indeed. – Peter Ruderman Jan 17 '13 at 19:58
1

If it's not too much for your introduction to presentation patterns, I'd urge you to take a look at the Presenter-first variant of MVP.

In this variant, and providing an answer to your question, the presenter knows both the model and view but only via interfaces. Neither the view, nor the model know of each other. The presenter co-ordinates each via events and methods.

http://atomicobject.com/pages/presenter+first

http://spin.atomicobject.com/2008/01/30/presenter-first-get-your-triads-talking/

Example:

Class Presenter {
    private IModel model;
    private IView view;

    void Presenter(IModel model, IView view) {
        _model = model;
        _view = view;
    }

    void Initialise() {
        // Attach handler to event view will raise on save
        _view.OnSave += HandleViewSave();
    }

    void HandleViewSave(){
        _model.Save(_view.GetStuffToSave());
    }
}

Very basic example but illustrates the point. The presenter is merely a conduit for communication between the view and model.

Creating the presenter can be done with Poor Man's DI or a proper container:

Presenter p = new Presenter(new CustomerModel(), new CustomerForm());

Note that AtomicObject recommend no reference to presenter, so it actually looks like this:

new Presenter(existingCustomerModel, existingCustomerForm);

existingCustomerModel.Initialise();

The fact that the model and view have scope means the presenter also stays in scope via its references... clever.

David Osborne
  • 6,436
  • 1
  • 21
  • 35
  • If presenter knows only `IModel` and not `Model`, how will I be able to call `model.Save();` under the `Save` event? Where do I get concrete instance of model for the presenter? Would the view pass it? In that case its contradicting the anwer from Peter. – nawfal Jan 17 '13 at 19:47
  • 1
    There's a few different variants of MVP, not to mention some 'colloquialisms' that have appeared along the way. Therefore, it's not unusual to find apparent contradictions and subsequent confusion. I'll flesh-out my answer with an example of how presenter-first works. However, AtomicObject's writing is the original, and best, source. – David Osborne Jan 17 '13 at 20:10
  • David thanks for the links, definitely informative, and yes I'd love to see the expanded answer.. – nawfal Jan 17 '13 at 20:11
  • thats exactly what I wrote in my question originally. My questions is where do I get `_model` variable from? Who passes the concrete instance? View right? So you're basically seconding my first approach right? – nawfal Jan 17 '13 at 20:21
  • Ok your subsequent edit makes it clear. Sadly that's in contradiction with Peter's answer.. May be its just a difference between Supervising Controller and Passive View approaches as Big Daddy says.. – nawfal Jan 17 '13 at 20:24
  • Something has to create your presenter to start with. Whatever this is creates concrete instances of the model and view and injects them into the presenter. Use a IoC framework or poor man's DI to do it. – David Osborne Jan 17 '13 at 20:24
  • 1
    Don't underestimate how complicated it can be to write a really effective application with this pattern. Of all the presentation patterns, this one definitely looks easy on the surface but can quickly become a tangled mess when the complexity grows. – David Osborne Jan 17 '13 at 20:27
  • Who owns the Presenter in this case? – Tash Pemhiwa Mar 30 '16 at 08:00
  • @TashPemhiwa That's a good question and it highlights one area where this pattern can get messy. Essentially, the presenter is owned by whoever/whatever needs to use its services. This could be an event, command handler, etc. – David Osborne Mar 30 '16 at 09:43
  • @DavidOsborne Appreciate it. I understand your 'messy' – Tash Pemhiwa Mar 30 '16 at 12:34