Jeremy D. Miller -- The Shade Tree Developer

Sponsors

The Lounge

Syndication

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Build your own CAB Part #5 - The Presentation Model

Our four friends are crafting a strategy for the inevitable and highly anticipated clash with the minions of the Lady de Winter.  Mighty Porthos has just finished a long oration about his Passive View approach to creating maintainable WinForms screens.  The crafty Aramis has started his own oratory on his preferred approach to avoid so much Interaction Based Testing by utilizing...

 

The Presentation Model

The Presentation Model differs from the two Model View Presenter approaches (Supervising Controller and Passive View) by combining the "M" and the "P" into a single class.  This single Presentation Model class both contains the state of the screen and implements the behavior of the screen.  Compared to the Supervising Controller, Presentation Model is more complex in that it also implements the state of the screen, but also less complex because the state synchronization is almost entirely the responsibility of the View itself.  Instead of a Presenter directing the View to change the state of the screen, the Presentation Model simply changes its own state and depends on Data Binding (or an equivalent) to update the screen accordingly. 

Let's jump right into our third and final implementation of the Shipping Screen.  As I stated before, the View will use data binding to bind its screen elements to the public properties on the new ScreenPresentationModel class.

    public partial class ShippingScreen : Form

    {

        public ShippingScreen()

        {

            InitializeComponent();

        }

 

        public void Bind(ShippingPresentationModel model)

        {

            shipmentBindingSource.DataSource = model;

        }

    }

I'll spare you the rest of the data binding setup code, and besides, that's covered in other literature to a vastly greater degree than Presentation Model.  Besides which, I've barely worked with data binding and you've probably guessed correctly that I'm more than a little biased against it.

So far we haven't seen anything that different from Supervising Controller, but when you use the Presentation Model approach you're probably exploiting the fact that data binding in WinForms can also bind to the "Visible" and "Enabled" properties of controls and not just the value.  In the case of the Shipping screen, we'll bind the "Enabled" properties of the checkbox's for selecting insurance and requiring a signature to properties on the ShippingPresentationModel shown below.

        public bool InsuranceEnabled

        {

            get { return _insuranceEnabled; }

            set { _insuranceEnabled = value; }

        }

 

        public bool SignatureEnabled

        {

            get { return _signatureEnabled; }

            set { _signatureEnabled = value; }

        }

 

        public string Vendor

        {

            get { return _vendor; }

            set

            {

                _vendor = value;

                fireChanged("Vendor");

 

                DeliveryOptions options = _service.GetDeliveryOptions(this);

                InsuranceEnabled = options.PurchaseInsuranceEnabled;

                SignatureEnabled = options.RequireSignatureEnabled;

            }

        }

In the above code, anytime a user selects a different shipping vendor the data binding will call the setter for Vendor on ShippingPresentationModel, causing a recalculation of the InsuranceEnabled and SignatureEnabled properties, which finally causes the two checkbox's to be either enabled or disabled depending upon the shipping vendor selected.  All because a little bug went kachooo!

The communication between View and the Presentation Model is relatively simple, the View simply sets properties on the PresentationModel class and cascading actions are triggered in the setters.  I've purposely put off talking about View to Presenter communication, but let's just say that this aspect of the Presentation Model is simpler than either Supervising Controller or Passive View.

One last example of the ShippingPresentationModel.  There are three or four factors that influence the cost of the shipment.  If any of these screen elements change, the cost needs to reevaluated.  With Presentation Model, I just capture all change events inside the setters, so the trigger to reevaluate the shipping cost is something like this:

        public string ShippingOption

        {

            get { return _shippingOption; }

            set

            {

                _shippingOption = value;

                fireChanged("ShippingOption");

 

                _service.CalculateCost(this);

            }

        }

 

        public bool PurchaseInsurance

        {

            get { return _purchaseInsurance; }

            set

            {

                _purchaseInsurance = value;

                fireChanged("PurchaseInsurance");

 

                _service.CalculateCost(this);

            }

        }

 

        public bool RequireSignature

        {

            get { return _requireSignature; }

            set

            {

                _requireSignature = value;

                fireChanged("RequireSignature");

 

                _service.CalculateCost(this);

            }

        }

I simply make a call to IShippingService.CalculateCost(IShipment) anytime a property changes that impacts the shipping calculation.  For convenience sake, I made ShippingPresentationModel implement a common IShipment interface that is consumed by IShippingService, if you're wondering where in the world the "this" parameter was coming from.  I'm assuming that the IShippingService will itself set the IShipment.Cost property.  The signatures for IShippingService still looks like this:

    public interface IShippingService

    {

        string[] GetLocations();

        string[] GetShippingVendorsForLocation(string location);

        string[] GetShippingOptions(IShipment shipment);

        void CalculateCost(IShipment shipment);

        DeliveryOptions GetDeliveryOptions(IShipment shipment);

    }

State Based Unit Testing

The biggest difference to me in using Presentation Model versus one of the MVP patterns is the shift to state based testing inside of our xUnit tests.  I'm more or less a "mockist" I guess, but I've worked with more than a few people who've had almost allergic reactions to using mock objects.  If you're one of those people, don't worry, you're not out of luck because you can do more or less state based testing with Presentation Model.  Here's an example of what I mean (even though out of pure contrariness I'm using RhinoMocks to create my stub):

        [Test]

        public void ResetTheShippingOptionsWhenTheStateOrProvinceIsChanged()

        {

            // We're going to test ShippingPresentationModel in a state-based manner

            // I'm using RhinoMocks to create the stub just because

            //   a.)  It's easy

            //   b.)  I hate cluttering up the code with static mocks and stubs if

            //        I don't have to.

 

            // You might note that I'm not even bothering to call mocks.VerifyAll()

 

            MockRepository mocks = new MockRepository();

            IShippingService service = mocks.CreateMock<IShippingService>();

            ShippingPresentationModel model = new ShippingPresentationModel(service);

 

            string[] theOptions = new string[]{"Option 1", "Option 2", "Option 3"};

            Expect.Call(service.GetDeliveryOptions(model)).Return(theOptions).Repeat.Any();

            mocks.ReplayAll();

 

            // We need to verify that the model starts with a zero array string

            Assert.AreEqual(0, model.ShippingOptions.Length);

 

            // I'm not sure I'd bother testing the raising of the PropertyChanged event,

            // or at least do it in another test.

            bool propertyWasCalled = false;

            model.PropertyChanged += delegate (object sender, System.ComponentModel.PropertyChangedEventArgs e)

                                        {

                                            propertyWasCalled = e.PropertyName == "ShippingOptions";

                                        };

 

            model.StateOrProvince = "TX";

 

            // Check that the state of the model changed

            Assert.AreEqual(theOptions, model.ShippingOptions);

 

            // And while we're at it, let's check that the PropertyNotified event was called

            Assert.IsTrue(propertyWasCalled);

        }

All I'm testing here is that the ShippingPresentationModel gets a list of Shipping Options whenever the StateOrProvince property is changed, then resets its ShippingOptions property.  I'm not real wild about it, but I also showed using an anonymous delegate to check that the PropertyChanged event was fired for "ShippingOptions."  To recap, the expected sequence of events is:

  1. The user selects a value in the State or Province select box.
  2. Data binding in the view sets the StateOrProvince property on ShippingPresentationModel.  Since the View is just talking directly to getters and setters, we really don't need the View involved in this unit test at all.
  3. In the setter for StateOrProvince, the ShippingPresentationModel should find the ShippingOptions for the selected state or province and set it's internal value for ShippingOptions which...
  4. Fires the PropertyChanged event for "ShippingOptions" which directs the magical data binding support to fill the dropdown list for Shipping Options with new values (which I didn't show because it's documented very well on MSDN).

Whew.  The code that implements this test above is much simpler:

 

 

        public string StateOrProvince

        {

            get { return _stateOrProvince; }

            set

            {

                _stateOrProvince = value;

 

                // Whenever this property changes, we need to reset the

                // ShippingOptions to match the StateOrProvince

                ShippingOptions = _service.GetShippingOptions(this);

 

                fireChanged("StateOrProvince");

            }

        }

 

 

        public string[] ShippingOptions

        {

            get { return _shippingOptions; }

            set

            {

                _shippingOptions = value;

                fireChanged("ShippingOptions");

            }

        }

 

 

 

Summary

The Presentation Model is another example of a Humble View.  It largely differs from the Model View Presenter patterns by combining the Model and Presenter into a single class.  It's important to note that the Presentation Model most likely encapsulates the actual application model, and it's definitely part of the user interface rather than a domain model class implementing pure business logic.  While it does a great job isolating behavior from the View and exposing the behavior in a way that allows for state based testing, you might find yourself getting annoyed at all the delegation that has to take place between the Presentation Model class and the inner application model.  Then again, a buffer between the user interface and the rest of the application might just be a good thing.

Honestly, I haven't used this pattern but a time or two.  The largest implementation I've seen was actually a Java Swing client where it was used quite effectively. 

I do have an example from StoryTeller that I will probably use in the posts on creating an Application Shell where I use Presentation Model as a kind of state machine to synchronize menu state as the screen mode changes.  I'm leaving it out now for the sake of brevity (and my impending bedtime).

Other Resources

  • I think Presentation Model is another name for the Model/View/ViewModel pattern being promoted by some of the WPF team at Microsoft.  I still think I'd rather stick with Supervising Controller in most cases, but I'm thrilled that people in MS itself are talking about this at all.
  • It's an old post, but I'd read Michael Swanson's thoughts on Presentation Model before you run off and use the pattern.

 

Three Musketeers Retirement Notice

The silly Three Musketeers thematic interludes just require more creativity than I can summon on a regular basis.  Let's just say they stopped the evil Lady de Winter in her diabolical mission (even though she's usually the most interesting character in the movie adaptations.  Seriously, who are you going to root for, Chris O'Donnell or Rebecca De Mornay/Faye Dunnaway?  That's what I thought;) and delivered their very complex WinForms application on time with minimal fuss with a healthy infrastructure of automated testing.  And for the hard core Dumas fans, let's just forget about how badly things end in the Man in the Iron Mask because it still depresses me in a way that has only been topped by "they killed Wash!."

 

Where Next?

I've got to tally up the poll on this one, but for the sake of narrative continuity I'm going to wrap up Model View Presenter with some quick and easy to write posts on View/Presenter communication and dividing roles.  After that, I'm not sure yet, but the response has been so positive that I'll definitely keep going for a while.  I will finish this by no later than mid July.  I'm shooting for 2-3 posts a week.


Posted Sun, Jun 3 2007 11:12 PM by Jeremy D. Miller

[Advertisement]

Comments

Steve wrote re: Build your own CAB Part #5 - The Presentation Model
on Sun, Jun 3 2007 11:56 PM

Thanks - good post

I'm using Billy McCafferty's MVP setup

(see more: www.codeproject.com/.../NHibernateBestPractices.asp)

It's good to see you cover the different types and your article shed light on ways I can utilize the MVP I'm developing with.

Thanks again

(PS. complex screens in MVP - that is a good topic - AJAX enabled where the customer wants to see multiple data - ie. a customer, his address, etc... ) all one screen.

Jeremy D. Miller wrote re: Build your own CAB Part #5 - The Presentation Model
on Mon, Jun 4 2007 8:21 AM

Steve,

Thanks for the comment, but these posts are aimed squarely at WinForms development.  It's not entirely safe to assume that things work exactly the same in the ASP.Net/WebForms world.

Jeremy

Cleve Littlefield wrote re: Build your own CAB Part #5 - The Presentation Model
on Mon, Jun 4 2007 2:43 PM

I love the series, and you have more clear made the subtle differences between these patterns.

However, I (and I assume a lot of others as well) learn better from seeing the code end to end.  Anyway you can ammend a zip file to each post to show the full code of the part?  This would help a lot.Doesnt have to really work, just would let people tie the pieces together.

Jeremy D. Miller wrote re: Build your own CAB Part #5 - The Presentation Model
on Mon, Jun 4 2007 2:48 PM

Cleve,

Ugh.  You're the second person to ask.  I don't really have end to end samples, but I will upload a zip of what I've got tonight.

Jeremy

jdn wrote re: Build your own CAB Part #5 - The Presentation Model
on Wed, Jun 6 2007 4:51 PM

Did you upload the zip anywhere?

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB Part #10 - Unit Testing the UI with NUnitForms
on Tue, Jun 26 2007 9:57 PM

I&#39;ve long, long since left the rails of &quot;Build your own CAB&quot; topics and wandered off into

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #11 - Event Aggregator
on Fri, Jun 29 2007 11:12 AM

I will finish &quot;Build your own CAB&quot; at least before Acropolis hits and makes it all obsolete

Greg King wrote re: Build your own CAB Part #5 - The Presentation Model
on Thu, Jul 5 2007 10:17 AM

Great series of articles, and thank you for recalling my memories of The Three Musketeers (I have read all 5 books).

Jeremy D. Miller wrote re: Build your own CAB Part #5 - The Presentation Model
on Thu, Jul 5 2007 11:06 AM

5?  There are 5?

The Three Musketeers

Twenty Years Later/After whatever it was

The Man in the Iron Mask

What else?

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #13 - Embedded Controllers with a Dash of DSL
on Fri, Jul 6 2007 12:40 PM

Just to continue the world&#39;s longest run on sentence. Before I start, here&#39;s the table of contents

Alan Avante wrote re: Build your own CAB Part #5 - The Presentation Model
on Tue, Jul 17 2007 11:03 AM

I still do not see where the presenter is actually instantiated.  You never show this piece of code...which, IMO, is key to bringing the whole thing together.  Is the presenter instantiated in the Page_Init?  Could you break down and show us ignoramuses exactly where the passive presenter is instantiated?  It's doubly confusing because you actually have a method from the presenter which tells the view of the instantiated presenter!

This looks like a chicken and egg scenario to me dude...

Alan Avante wrote re: Build your own CAB Part #5 - The Presentation Model
on Tue, Jul 17 2007 11:07 AM

Add me to the list of people who would truly appreciate the end to end code, or any reasonable facsimile of this.

It's an excellent series of articles, but if the gaps are not closed, it's like building an eighth wonder of the world and not uncovering the thing so people can see it in it's full glory.

Jeremy D. Miller wrote re: Build your own CAB Part #5 - The Presentation Model
on Tue, Jul 17 2007 12:35 PM

Alan,

This isn't particularly a quick question to answer, but...

1.)  This series is specific to WinForms and I wouldn't try to apply it directly to ASP.Net.  I'd recommend looking at Igloo in Castle for more on MVP with WebForms.

2.)  It is chicken and egg, but in my case the Presenter is predominant, not the View.  I navigate to a Presenter object that has some sort of exposed .View {get;} property.  The View, and anything else the Presenter needs, is usually pushed into the Presenter via Dependency Injection.  My systems generally use StructureMap for DI.

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #14: Managing Menu State with MicroController's, Command's, a Layer SuperType, some StructureMap Pixie Dust, and a Dollop of Fluent Interface
on Tue, Jul 24 2007 5:18 AM

The title is a mouthful and accurately implies an alarmingly high jargon to code ration, but I just didn&#39;t

Jeremy D. Miller -- The Shade Tree Developer wrote The Build Your Own CAB Series Table of Contents
on Wed, Jul 25 2007 9:21 PM

Yes, this is overdue. Here is an introduction and table of contents to my &quot;Build Your Own CAB&quot;

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #14: Managing Menu State with MicroController's, Command's, a Layer SuperType, some StructureMap Pixie Dust, and a Dollop of Fluent Interface
on Thu, Jul 26 2007 10:57 AM

The title is a mouthful and accurately implies an alarmingly high jargon to code ration, but I just didn&#39;t

Jeremy D. Miller -- The Shade Tree Developer wrote Development Trivial Pursuit: The difference between MVC and the different flavors of MVP
on Wed, Oct 31 2007 9:12 PM

You can happily go your entire career without knowing the textbook definitions of either pattern and

Jeremy D. Miller -- The Shade Tree Developer wrote Resources from my DevTeach talks
on Thu, Nov 29 2007 12:03 PM

To everybody that attended one of my talks at DevTeach this week. All of the materials are now online

江南白衣 wrote View to Presenter Communication(转)
on Sat, Aug 2 2008 7:41 AM

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

Add a Comment

(required)  
(optional)
(required)  
Remember Me?