Build your own CAB Part #4 – The Passive View

When last we left our brave companions, between courses of cheese and fine wine, Athos was sharing his strategy for dividing screen responsibilities by employing the Supervising Controller pattern.  Mighty Porthos suddenly cleared his throat and exclaimed “since I am the strongest man in all of France, I would face my opponents a different way.  Because the View itself is the trickiest piece of code to test and maintain, I would squeeze the View with great force until the only thing left inside the View is a mere skeleton of presentation logic.  I will render the Lady de Winter’s greatest warrior a mere…

Passive View

Last time we looked at a small screen that allows a user to select options for configuring the shipment options for some sort of online order.  We examined a sample approach utilizing the Supervising Controller variant of Model View Presenter that left the View in charge of simple screen synchronization while utilizing an external Presenter class to handle more complex behavior and all communication with the rest of the system.  This time around we’re going to build the exact same system, but use the Passive View variant of Model View Presenter.

It’s probably easiest to explain Passive View by first explaining how it’s different than Supervising Controller.  The goal of the Passive View is to maximize the ability to automate testing of the screen, and that means taking as much as possible out of the hard to test View code and moving it to the Presenter.  For that reason, the biggest difference is the reduced role of the View — even from the already slimmed down View attached to a Supervising Controller.  The Presenter/Controller is responsible for all screen synchronization.  The View in Passive View is an extremely thin wrapper around the presentation details with next to no behavior of its own.  The view probably doesn’t even know about the Model classes.  To start the Passive View solution, let’s look first at the interface for IShippingScreen:

    public interface IShippingScreen

    {

        string[] ShippingOptions { set; }

        string[] Vendors { set; }

 

        bool InsuranceEnabled { set; }

        bool SignatureEnabled { set; }

 

        string StateOrProvince { get; set;}

        string Vendor { get; set;}

        string ShippingOption { get; set;}

        bool PurchaseInsurance { get; set;}

        bool RequireSignature { get; set;}

        double Cost { get; set;}

    }

As you can probably guess from this interface alone, the View becomes simplistic.  The Presenter is now responsible for telling the view what piece of information to put into each UI widget.  The concrete View is going to end up looking something like this:

    public partial class ShippingScreen : Form, IShippingScreen

    {

        public ShippingScreen()

        {

            InitializeComponent();

        }

 

        public string ShippingOption

        {

            get { return shippingOptionField.SelectedText; }

            set { shippingOptionField.SelectedText = value; }

        }

 

        public bool PurchaseInsurance

        {

            get { return purchaseField.Checked; }

            set { purchaseField.Checked = true; }

        }

 

        // Who sees a problem here?

        public double Cost

        {

            get { return double.Parse(costField.Text); }

            set { costField.Text = value.ToString(); }

        }

 

        // Stuff that we don’t care about

        #region Stuff that we don’t care about

 

        #endregion

 

    }

At this point, the view is as dumb as we can possibly make it.  It should be nearly trivial to verify the functioning of the View code by simple inspection — for the most part anyway.  We could easily decide to forgo testing the actual View itself at this point and judge that to be a perfectly acceptable compromise.

The Presenter is now more complicated because it’s taking on the additional responsibility for synchronizing data between the screen and the Domain Model.  In this case it’s making a one to one transference of properties from the screen elements to the properties of the Shipment class.

        private Shipment createShipmentFromScreen()

        {

            Shipment shipment = new Shipment();

            shipment.PurchaseInsurance = _screen.PurchaseInsurance;

            shipment.StateOrProvince = _screen.StateOrProvince;

            // so on, and so forth

 

            return shipment;

        }

For a small screen, that’s not that bad.  In reality, I generally use Passive View for small screens like login screens.  I do find the screen synchronization to be a chore.  Then again, think about the case of a screen that serves to display and edit an aggregate object structure with multiple levels of hierarchical data.  Data binding works best with “flat” objects, so you’ve got to do something.  In my mind, sacrificing the structure of the business domain to fit the user interface tooling is mostly a poor compromise.  To have the best of both worlds you can either create a wrapping object to provide a “flattened” view of the object hierarchy to allow data binding to work, or skip that and use Passive View to have better control over the screen synchronization. 

What is cool about Passive View, besides the extra testability, is a further set of insulation between the presentation technology and the business and service layers of the application.  When I built the Supervising Controller approach, I deliberately used an object specifically built for the data binding and hid the “real” domain behind IShippingService.  This time around, let’s let the Presenter work with the “real” domain classes somewhat.  That being said, ShippingScreenPresenter will now interact with an IShipper class to get at the business rules for a particular shipping option. 

    public interface IShipper

    {

        bool AcceptsInsurance { get;}

        bool CanRequireInsurance { get;}

        string[] Options { get;}

        string Description { get;}

 

        bool CanCaptureSignature { get; }

 

        double CalculateCost(Shipment shipment);

    }

Of course, we’ve got to find the correct IShipper in the first place.  For that, we’ll use a Repository:

    public interface IShipperRepository

    {

        IShipper[] GetShippersForLocation(string location);

        IShipper FindShipper(string shipperName);

    }

Even more so this time, the ShippingScreenPresenter is largely a Mediator between the interfaces exposed by IShippingScreen, IShipper, and IShippingRepository.  The screen synchronization can be more work inside the presenter, but I think you can get by with less abstraction of the rest of the application.  The ShippingScreenPresenter might look like this:

    public class ShippingScreenPresenter

    {

        private readonly IShippingScreen _screen;

        private readonly IShipperRepository _repository;

        private IShipper _shipper;

 

        public ShippingScreenPresenter(IShippingScreen screen, IShipperRepository repository)

        {

            _screen = screen;

            _repository = repository;

        }

 

        public void ShipperSelected()

        {

            _shipper = _repository.FindShipper(_screen.Vendor);

            _screen.ShippingOptions = _shipper.Options;

            _screen.InsuranceEnabled = _shipper.CanRequireInsurance;

            _screen.SignatureEnabled = _shipper.CanCaptureSignature;

        }

 

        private Shipment createShipmentFromScreen()

        {

            Shipment shipment = new Shipment();

            shipment.PurchaseInsurance = _screen.PurchaseInsurance;

            shipment.StateOrProvince = _screen.StateOrProvince;

            // so on, and so forth

 

            return shipment;

        }

 

        public void OptionsChanged()

        {

            Shipment shipment = createShipmentFromScreen();

            _screen.Cost = _shipper.CalculateCost(shipment);

        }

    }

Needless to say, using the Passive View pretty well demands an Interaction Testing style of unit tests with lots of mock objects.  If you don’t grok RhinoMocks, Passive View might not be for you.  Supervising Controller is a definite alternative, but in a later section I’ll take a look at the Presentation Model pattern for a state-based style of unit testing.

Interlude

Young D’Artagnan looks puzzled.  He finally asks his older friends “Wouldn’t that make the communication between the Presenter and View very chatty?  And what’s to stop the Presenter from becoming just as convoluted as an Autonomous View?”  Porthos snorts and exclaims “You are a perspicacious lad!  I would not stop with crushing the View into submission.  I will use my superior strength to crush the Presenter until it only contains a single, cohesive responsibility!”

Summary

I used Passive View quite extensively on my first WinForms project in 2004.  Overall, the experience hooked me for life on using Humble Dialog Box design philosophies for building fat clients.  It became routine for screens to work on the very first attempt to run new screen features — assuming that you really did unit test the individual pieces first.  We also so another noticeable trend, screens that were fatter with more logic and less unit test coverage generated alarmingly more bugs and took much more time to debug.   

I mentioned that the screen synchronization can become a chore.  The presenter potentially picks up more responsibilities for screen synchronization and state like “IsDirty” checks.  The downside of Passive View is a chatty interface between View and Presenter.  I wrote an article early last year detailing my Best and Worst Practices for Mock Objects.  Most of the advice for what not to do with Mock objects came from that same project that we used Passive View.  My advice is to watch the size of the Presenter.  If it gets too big, split up responsibilities.  Maybe you take screen synchronization, IsDirty logic, and maybe validation and put it in some kind of “inner” presenter.  The “Inner” presenter talks to the View itself.  The “Outer” presenter talks to the “Inner” presenter and the outside world. 

One way to detect a need for this Inner/Outer presenter case is to watch your unit tests.  If you ever find yourself writing an uncomfortable number of mock object expectations in any one test, you’re probably violating the Single Responsibility Principle (SRP).  If you find yourself setting up mock object expectations for something that’s barely relevant to the subject of the unit test, you almost automatically split the class under test into multiple classes.  One of the best design tricks you can apply is to continuously move your design closer and closer to SRP.

Conclusion

The four friends finished their repast and sat around the fire, sated from the provisions generously supplied by a minor noblewoman of Atho’s acquaintance.  Aramis, who the companions know is the craftiest of the four friends, speaks up:  “slaying a View of many responsibilities with the sharp edge of a mock object is a fine thing, but I think that we can use our wits to fool the screen into  subservience to state based testing by employing the Presentation Model to…”

To be continued in Part #5 – The Presentation Model — unless you’d rather talk about something else.

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.
  • Rod

    Hi Jeremy,

    I want to rephrase my #1 question, Adding Cost interface IShippingScreen view will violate the Supervising Controller pattern? or its a matter of Service vs. Repository/Domain?

    Cheers!
    Rod

  • Rod

    Hi Jeremy,

    The Best MVC-MVP article I’ve read!!! Good work!!!

    After creating a sample project to put all interface into action by adding shell and UI I came up with the following questions:

    1. Can we combine Passive View and Supervising Controller? Like in the case of the Shipping sample in Supervising Controller, can we add a Cost interface in IShippingScreen view inorder that everytime the Shipment_PropertyChanged event is raised in Presenter Cost field is automatically updated.

    2. Is it a good approach to inherit a view interface(s) in another view to combine interfaces into one view. In my experiment I created a IFormView out of the “The Humble Dialog Box” sample and I inherit IFormView in ISheepingScreen view (see Fig 1.0), that way when I inherit ISheepingScreen in my Form (UI) it will have the both ISheepingScreen and IFormView view interfaces (see Fig 2.0).

    Fig: 1.0
    public interface IShippingScreen : IFormView
    {
    ….
    }

    Fig: 2.0

    public partial class MyForm : Form, IShippingScreen
    {

    }

    Fig: 2.1

    public partial class MyForm : Form, IShippingScreen, IFormView
    {

    }
    Do you prefer inheriting view (see Fig 2.0) or just inherit them separately in the Form (UI) (see Fig 2.1)

    Thanks in advance!
    Rod

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

    Jason,

    All bets are off when you get to needing a Grid. That alone will force you to a Supervising Controller. I think 3rd party controls, and especially grid controls, are one of the last redoubts of untestable code.

  • Jason

    My interpretation is that with the Supervising Controller variant the View Interface can take the Model (entities) as parameters but in Passive View (PV) it is limited to primitive types that map directly to the UI elements.

    The question that I have is how you deal with grids etc. with PV? For example what if you have a List and want to display in a pageable / sortable form. The ASP.NET GridView control is (deservedly) much maligned but you do get a lot of functionality for free.

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

    I know I am late, but I need to ask this (till this moment…i haven’t read the rest of the series…i hope i am not asking an answered question).

    but, I am still caught in the place where you tie the events together; I have an event handler for changing the Shipper in which i will call ShipperSelected(), ok cool…now by consequence i will execute the line:
    _screen.SignatureEnabled = _shipper.CanCaptureSignature;

    but i expect that the Signature Check box will have an event handler that would say SignatureChanged or something (in the case the user changed by his choice), then…that is called..i will be recalculating the view because i would expect a code close to what exists in ShipperSelected().

    in some cases we will have two controls that change each other in which we could have infinite loop. how to solve this in a good manner?

    in the crazy code i ended up with (i know it’s not the best answer…but it worked..and i want better answer that what i have)…i produce a flag …that would tell me what was the cause of the data moving…(is it the users click?..or another control in the form)…if it was the user..i change it to THE control…and do the code..and then reset it to Neurtral.

    i don’t like this, is there better thing that suits the sweetly-though series?

    thanks for your valuable posts,
    Emad

  • ulu

    @Jeremy
    “I’m not sure about your reasoning. Offhand that seems to almost completely defeat the purpose of doing the MVP split in the first place.”

    The View and the Presenter are still separate classes. So the split is there. All the methods and properties from your post are there. The idea is to make the Presenter a private class within View. So, you can’t call the methods of the Presenter from any other class but the View, but the Presenter still can manipulate the View, get the data from other classes etc.

    But of course, testability could be a problem here. Perhaps a lot of reflection could do that. Of course, that depends on the situation. It might be that having methods like ShipperSelected() public is undesirable, and you are willing to make some extra effort and test a private Presenter.

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

    @ulu,

    I’m answering some of this in another post.

    Making the View “Passive.” You might be reading that too literally. The classic OO truism *is* to make the class with the data responsible for doing stuff to that data (Information Expert), but in this particular case I think that testability buys me more than encapsulation. The View’s responsibility is just to manipulate the Control state inside. It’s not like the Presenter is reaching into the View to set values directly on a CheckBox or TextBox.

    Keep in mind that Passive View isn’t the only way to do things.

    “perhaps a good idea would be to make the Presenter a private class of the View?”

    I’m not sure about your reasoning. Offhand that seems to almost completely defeat the purpose of doing the MVP split in the first place.

  • ulu

    Jeremy,

    First let me thank you for the great series. Not only your articles smart and clear, they are a big fun to read!

    Now to the point. I recall that it is the very basic principle of OO programming that you shouldn’t make your objects passive, instead, you should let the object maintain itself. Otherwise, you end up with a sort of procedural programming. Your View class seem to contradict this idea. Also, everybody says that anemic models are just bad, but what about anemic views?

    Now, I absolutely agree that this model is much easier to test (with RhinoMocks and without NUnitForms), but here’s another question that’s been left unanswered elsewhere: should we design for testability, or should we try and test what’s designed (perhaps designed badly, so we refactor later)?

    Another thing that seems to be against the OO basics here: we are forced to make the InsuranceEnabled property public, which might be against our idea that other views (and presenters, and services) shouldn’t be able to access this property. So, if we really want to keep the separation, perhaps a good idea would be to make the Presenter a private class of the View?

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

    I LOVE the thin view dude!!! Got all excited when finally seeing a view that does not have GUI Control Event Handlers (_checkedchanged events, _selectedValueChanged, etc.) and no reference to “_myPresenter” …until I saw in the ShippingScreenPresenter class the method “public void ShipperSelected()”…surely the view still needs to have a “_myPresenter” variable, along with a call to “_myPresenter.ShipperSelected” in the cbxShippingVendor combobox’s SelectedIndexChanged event? Or am I missing something? If I am correct, I guess this post is an affirmation of what GJK said on May 31st – please post more complete classes – not necessarily working code, but more complete classes will help affirm the concepts you are trying to get across – even if you include more comments in the classes like “this type of code goes here”, “that type of code goes there”…that kind of thing – so that the whole picture is still kept in play.

  • Rick Donaldson

    Could you post an example of a more complicated view being used? For example, if your form contains a treeview control, would you add AddTreeItem()/RemoveTreeItem() methods to the view interface or would you create a platform-independent treeview wrapper or perhaps something else?

  • GJK

    As always, love the series of articles. BUT could you please post some working source code. What I am not understanding from reading about it I will learn from seeing it work.

    Please.