Build your own CAB Part #6 – View to Presenter Communication

If you’re reading this post and wondering about 1-5, you might give the previous posts a perusal first.  This post (hopefully) builds on the previous posts in this series.

Build your own CAB Table of Contents

  1. Preamble
  2. The Humble Dialog Box
  3. Supervising Controller
  4. Passive View
  5. Presentation Model

View to Presenter Communication

Alright, I’ve purposely hid the View to Presenter communication in my previous posts on Supervising Controller and Passive View because I thought that subject was worthy of its own post.  As I see it, there are 2 1/2 basic ways to communicate screen events back to the Presenter.

  1. Expose events off of the IView interface.  Jeffrey Palermo has told me before that he will do something very similar, but attaches delegates through setter properties instead.  I’m calling that technique the “1/2″ because it feels very similar to me to using events.
  2. Let the View have a reference to the actual Presenter and just call methods on the Presenter inside of screen events.

Just taking a straw poll of the blog posts out there about this topic, the majority of the world seems to favor events.  Just to be contrary, I very strongly prefer direct communication and it’s time for that approach to get some love .

 

Doing it with Events

Making the View to Presenter communication work through events has the indisputable advantage of maximizing loose coupling.  The View doesn’t even need to know that there’s anything out there listening.  It’s just shouting in the dark hoping someone will answer with help.  There’s no need to pass around instances of the Presenter, so wiring MVP triads together is a little bit simpler.  Let’s take a look.  The first step is to define the proper events on the View interface.  Here’s an example from the Shipping Screen first described in the Supervising Controller post.

    public delegate void VoidHandler();

 

    public interface IShippingScreen

    {

        event VoidHandler ShippingOptionChanged;

        string ShippingOption { get;}

    }

The ShippingOptionChanged event is the interesting thing here.  When this event fires, the Presenter needs to recalculate the cost of the selected shipment and decide whether or not other shipment options for purchasing insurance or requiring a signature are still valid.  The actual View implementation is to simply relay the screen event with no interpretation:

        public ShippingScreen()

        {

            InitializeComponent();

 

            shippingOptionField.SelectedIndexChanged += new EventHandler(shippingOptionField_SelectedIndexChanged);

        }

 

        void shippingOptionField_SelectedIndexChanged(object sender, EventArgs e)

        {

            if (ShippingOptionChanged != null)

            {

                ShippingOptionChanged();

            }

        }

Now, on the Presenter side we have to register the event handler.  Since the event has a no argument signature, all we have to do is basically tell the screen which method on the Presenter to call.  No ugly anonymous delegates or ugly new SomethingDelegate(blah, blah) syntax.

    public class ShippingPresenter

    {

        private readonly IShippingScreen _screen;

 

        public ShippingPresenter(IShippingScreen screen)

        {

            _screen = screen;

 

            // Attach to the event in the constructor

            _screen.ShippingOptionChanged += this.ShippingOptionChanged;

        }

 

        public void ShippingOptionChanged()

        {

            // fetch the state the Presenter needs inside this operation

            // from the Vjiew

            string option = _screen.ShippingOption;

 

            // do whatever it is that you do to respond to this

            // event

        }

    }

And yes, I would definitely make the event handler methods public.  I think you should do at least one unit test to verify that you’re wired to the correct event handler on the View interface, but otherwise I think you’ll find it much more convenient to test the ShippingOptionChanged() method by calling straight into the ShippingOptionChanged() method.  I know the semantics of the unit test are simpler when you do it that way.

Assuming that you are going to unit test by simulating the event being raised, your unit test for the functionality above will look something like this (assuming that you use RhinoMocks anyway):

        [Test]

        public void HandleTheShippingOptionChangedEvent()

        {

            MockRepository mocks = new MockRepository();

            IShippingScreen screen = mocks.CreateMock<IShippingScreen>();

 

            // Keep a reference to the IEventRaiser for ShippingOptionChanged

            screen.ShippingOptionChanged += null;

            IEventRaiser eventRaiser = LastCall.IgnoreArguments().GetEventRaiser();

 

            // other expectations here for the Presenter interacting with both

            // the backend and the View

 

            mocks.ReplayAll();

 

            // Raise the event

            ShippingPresenter presenter = new ShippingPresenter(screen);

            eventRaiser.Raise();

 

            // Check the interactions

            mocks.VerifyAll();

        }

The thing to note is how we grab onto the event with RhinoMocks to simulate the event.  In a normal test harness I usually build the presenter under test and all of the mock objects in the SetUp() method.  That requires a little bit of knowledge about RhinoMocks to keep the tests running correctly.  Check out the links at the bottom to Phil Haack and Jean-Paul for more information on how to do this.

Direct Communication

Why do I prefer direct communication?  Two reasons.   

  1. “CTRL-B” and “CTRL-ALT-B.”  If the this isn’t ringing a bell, these are the ReSharper keyboard shortcuts you use inside one method to quickly navigate to another method (or class or interface or delegate, etc.).  I think it’s easier to understand the codebase when there’s a direct semantic link from View to Presenter and vice versa.  With direct communication I think the code is more intention revealing.  When I look at the View code I know more about what happens when a dropdown value changes.  With events there’s more mechanical steps to figure out what’s registered for the event.
  2. I think the mechanics for mocking events are awkward (I don’t particularly have a better suggestion than what RhinoMocks does now).  Heck, I think events in general are awkward and I’ve never liked them.  I would rather just treat my Presenter like an Observer of the View so I can make all of the event notification registration in a single line of code in the Presenter. 

So the obvious downside is that now the View has to know about the Presenter, which spawns a new design question – who begat’s who?  The majority of the time I say that it’s a Presenter-centric world.  I create the Presenter first with the View coming in as a constructor argument.

    public class ShippingScreenPresenter : IShippingScreenObserver

    {

        private readonly IShippingScreen _screen;

 

        // The view is injected in through the constructor

        public ShippingScreenPresenter(IShippingScreen screen)

        {

            _screen = screen;

        }

 

        // I suppose you could do this operation in the constructor instead, but

        // it always feels so wrong to do much more than set fields in a constructor

        public void Start()

        {

            // bootstrap the screen

            _screen.AttachPresenter(this);

        }

 

        public void ShippingOptionChanged()

        {

            // do what you do so well

        }

    }

I usually have some sort of explicit call to a Start() method on my Presenter’s to bootstrap the screen.  In this case, the very first operation in Start() is telling the View about the Presenter.  I know what you’re thinking, this is going to tightly couple my View to the Presenter.  What if I want to use a different Presenter with the same View (it’s not that uncommon)?  What if I want to test the View itself?  The easy answer is to treat the Presenter as an Observer of the View.  In my DevTeach talk I brought up the tight coupling issue and promptly did an “Extract Interface” refactoring with ReSharper to show how easy it was to decouple the View from the concrete Presenter.  No one was impressed.  The View only sees:

    public interface IShippingScreenObserver

    {

        void ShippingOptionChanged();

 

        // all other callback methods for screen events

    }

The event handlers in the View itself get reduced to an immediate call to the Presenter (in bold).

    public partial class ShippingScreen : Form, IShippingScreen

    {

        private IShippingScreenObserver _presenter;

 

        public ShippingScreen()

        {

            InitializeComponent();

 

            shippingOptionField.SelectedIndexChanged += new EventHandler(shippingOptionField_SelectedIndexChanged);

        }

 

        void shippingOptionField_SelectedIndexChanged(object sender, EventArgs e)

        {

            _presenter.ShippingOptionChanged();

        }

 

        public void AttachPresenter(IShippingScreenObserver presenter)

        {

            _presenter = presenter;

        }

    }

In the section on MicroController, I’ll show how my project is creating the screen behavior for calls to the Presenter.

 

Best Practices in either case

The single best advice I think I could give is to make the communication as simple as possible.  As much as possible, make the callbacks and event handlers to the Presenter take in zero arguments.  Make the Presenter go back to the View and/or the Model to get current state.  On one had it makes the View simpler by eliminating code from the marginally testable View, on the other hand it decouples the View from needing to “Know” what the Presenter needs for its behavior determinations.  The exception cases would be for things like double clicking a single line inside of a grid to launch a new screen.  In that case I think the simplest thing to do is to send over just enough information in the handler for the Presenter to know which data member was the subject of the event.

The other advice I’ll give is to make the method names for event handling on the Presenter be as descriptive as possible.  Ideally, you should be able to almost entirely comprehend the behavior of a screen from looking at the Presenter alone.

I’ll talk about integration testing in later posts in this series.

 

Other Viewpoints

I’m fully aware that I’m almost a deviant by preferring direct calls from the View to the Presenter.  Here’s the other side:

In the end, just talk it over with the rest of your team and decide if you want to be a cool kid like me or a slave to Microsoft’s obsession with ugly event handling syntax, not that I want to prejudice you in any way;)

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Build your own CAB, Design Patterns. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://twitter.com/jeremydmiller jeremydmiller

    Start() on the presenter would be called by what I was calling a “Screen Coordinator”. It’s probably just a role on your ApplicationController. It would be part of your application shell rather than part of any given screen.

  • Uphaar

    I have been reading your series jeremy (and i know its been a while since you have written this), but my question was where would the start method be called. Certainly not on the View since calling presenter.Start() on the view will give you a Null Reference Exception. So where would the start be called ?

  • http://www.illede.net rüya tabiri

    Thank You..

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Jack,

    I’m sorry, but you’ve got to put me in the camp of people who think that pattern is unsuitable for anything but the simplest “forms over the web” screens. That effectively negates the usefulness of MVP by collapsing everything down to just the “V.”

    If you’re using it and it’s working, go for it.

    Jeremy

  • jack

    what about using typed datasource controls in asp.net which will do insert,update and delete without writing a line of code ,as produced by nettiers.Is is a good solution? How to do it using MVP?

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Definitely that. At some point you might say that you’ve cut you’re forms thin enough that it isn’t that risky to leave the views untested. Going to Events doesn’t change the testability equation in the slightest though. You’ve still got to prove (or just not worry about) that clicking a button raises the proper event in the public interface that the presenter sees.

  • Jason

    I was afraid that you were going to say that! I agree that the Direct Communication option is more expressive than Events but IMHO NUnitForms (or Selenium etc. for the web) tests are far more flaky than simple unit tests. So I’m jumping on the events and CTL+ALT+F7 in R# bandwagon. Thanks for the great series.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Jason,

    Quite easily actually. We attach a mocked presenter and use NUnitForms to perform the mouse clicks and other events on the screen and use RhinoMocks just to check that the right method on the presenter is called.

    Likewise for the event model. You just attach anonymous delegates to the View events.

  • Jason

    With the 2nd (Direct Communication) option how do you test that the view is correctly wired up to the presenter?

  • http://codebetter.com/blogs/john.papa John Papa

    Great blog post, Jeremy.

    I am a fan of the MVP Passive View pattern. I recently found myself readdressing this exact issue and I chose to stick with using events. I used the direct hookup in the past and while I enjoyed the CTRL-B goodness (yes, I am a R#’er fanatic) it always seemed to smell to me. There was nothin i could ever tangibly point out that was causing the smell either. It was like a hit and run in the men’s locker room. :)

    I am currently on a new project that I am architecting. I am reexamining all of my current practices and tweaking here and there.

    One new feature I recently began using is a slim WCF layer between the Presenter and the Service Layer. I used Dependency Injection to get the WCF Service Contract into the Presenter and it works like a champ. The separation is nice and loose, although I had to create a WCFServiceInterface assembly that so both the presenter and the WCF Service could see that. You just don’t see much WCF out there.

    My next examination is if I want to integrate some sort of repository in the Domain Model. I currently have Service Layer that coordinates the requests for Domain Model Entities through a Mapper (and then on to the DAL and to the DB). My clients have never gone for OR Mapping tools due to their open source fear and I certainly don;t want to build one (especialy since I think Entity Framework will be a good choice when they resolve a lot of the current issues and tidy it up).

    Anyway, just wanted to share and say that I have been enjoying your posts, even though we disagree on the implementation of the events in tis case :)

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Jens,

    You could do all that work in the constructor, but that’s kind of smelly in a way. Every unit test will have to remember to accomodate the stuff that’s happening in the constructor — and that’s what I wanted to avoid.

    Plus there’s the very real possibility that the Presenter gets bootstrapped differently in different scenarios. A “StartNewTrade()” method versus “DisplayTrade(Trade trade)” method for creating versus updating.

    As to forgetting to call Start()? That’s going to be very easy to detect since the screen won’t work without it. Besides, much of the time some sort of ApplicationController will be calling those methods as Presenter’s are made active.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Derrick,

    That’s nice, but again, where does that event go? Who’s listening? What happens? Can you tell by reading the code?

    The wiring may be easier to develop mechanically, and I’m a bit dubious on that as well, but the understandability of the code is definitely compromised. It’s a cool solution for really complicated composite views.

    All the reflection going on might have something to do with the performance problems in CAB I’ve heard complained about too.

    It’s a classic Microsoft solution. They’ve optimized the “first write” while sacrificing maintainability.

  • http://www.jenswinter.com Jens Winter

    Hello Jeremy,

    Did I spot a small drawback with your approach here? You have to always remember to call presenter.Start(); in order to get the presenter attached to the view.
    And besides that you have to be aware of NullReferenceExceptions within the view in case the presenter hasn’t been attached. Perhaps some kind of NullPresenter (Null Object pattern) should be introduced to handle that scenario better.

  • D Rapp

    Dare I mention the product this blog series is meant to replace, but the SCSF (CAB gone wild) tackled View -> Presenter communication in an interesting manner: Attributes. It’s been a while since I’ve explored the SCSF inner-workings but by registering with the view various Command names, framework code can scan your application for code designed to listen for those commands. To specify a new listener, simply tag your event handler method in your presenter like this:

    [CommandHandler(CommandNames.ChangedShippingOption)]
    public void HandleChangeOfShippingOption(object sender, EventArgs e)
    {

    }

    The advantage (and simultaneous drawback) of this approach is that you can have a presenter responsible for an entirely different section of the UI be notified when the shipping option is changed. For instance, maybe you have a progress bar in the footer of the app scroll from 0 to 100 if computing new shipping options is a lengthy process…

    I think it deserves some mention.

  • SteveJ

    Great! Thanks for the great series (and great blog).

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @SteveJ,

    If it’s okay, I’m gonna write a separate post to answer your questions tonight.

    Jeremy

  • SteveJ

    So does the presenter provide the data from the model to the view, or does the view also have a reference to the model? Or does it depend on which of the patterns from earlier in the series that you pick?

    I’m still wrapping my head around the Presenter. Is it tightly coupled to the view? For instance if I have some code that says turn these fields blue when the user does x, does that code live in the presenter or the view?

    I have read the previous articles (may not be apparent from the questions), but I think the sheer diversity of options has just completely thrown me.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Nice Bill. I blew off generics for quite a while but they’re so handy for things like this.

    I’m definitely getting around to a Layer SuperType discussion for the Presenter and View when I hit the sections on the ApplicationShell.

  • http://blogs.meetandplay.com/wpierce/ Bill Pierce

    Hey Jeremy,
    To save some myself some typing when creating views and presenters I started with these simple interfaces:

    public interface IPresenter
    {
    IView View { get; }
    }

    public interface IView
    {
    void SetPresenter(IPresenter presenter);
    }

    public interface IPresenterBase : IPresenter where T : IView
    {
    new T View { get; }
    }

    public interface IViewBase : IView where T : IPresenter
    {
    void SetPresenter(T presenter);
    }

    Then just add a base view that inherits from Control/Form and implements IViewBase and it will save you quite a bit of typing in the long run.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Marlun,

    Try here: http://www.martinfowler.com/eaaCatalog/applicationController.html

    “ApplicationShell” is just my name for the main Form.

    As for the rest, I’m getting there…

  • Marlun

    Ah, I havn’t really got into the Inversion of Control tools yet, I’ll have to look into StructureMap. I also don’t know the ApplicationController or ApplicationShell which I think you had as possible subjects for articles, I’ll just have to wait some :)

    Right now I’ve only got the default Program.cs which does Application.Run(new MainView());

    I’ll go search for information about ApplicationController and ApplicationShell. I believe I’ve read about the ApplicationController but for web development in PHP, not sure if it’s the same thing but we will see.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Marlun,

    I was going to address that very subject, but got lazy and published it as is. I say it’s a Presenter-centric world, and all navigation and screen activation happens by creating a Presenter first, then fetching the View from the Presenter. In a real system the construction of the View to the constructor of the Presenter is always done with an Inversion of Control tool. In my case it’s StructureMap (http://structuremap.sourceforge.net).

    I will have the View construct the Presenter the way you’re describing on occasion, but it’s the exception not the rule.

    This is a topic for a later post in this series, but something like this would be in the ApplicationController:

    IPresenter nextScreen = ObjectFactory.GetNamedInstance(“name of screen”);

    nextScreen.Activate();

    shell.ShowView(nextScreen.View);

  • Marlun

    Thanks again for a great article! I’ve got a question: Where does the IShippingScreen come from in the presenter contructor?

    In the code I’ve done now the view is created first and then it creates a presenter and sends itself into it. Why are you doing it the way you are doing it? Is it to take the responsibility of hooking them together from the view?