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 #3 - The Supervising Controller Pattern

When last we left D'Artagnan he had just concluded a successful duel with a number of screen concerns by dividing them with a masterful usage of the Humble Dialog Box.  As D'Artagnan strives to regain his breathe, he's heartened by the appearance of his three doughty companions Athos, Aramis, and Porthos.  As the four friends sit down in a shady spot besides the road for a fine meal of delicacies (unknowingly donated by a noblewoman of Athos' acquaintance), D'Artagnan describes their predicament when they manage to corner the Lady de Winter and her host of minions.

A Shipping Screen 

Let's imagine that you need to build a little screen to allow a user to configure the shipping options for some sort of electronic order that looks something like this screenshot below:

The user first needs to select the state or province (since this was for a talk in Canada, I thought it would be nice to let our Canuck neighbors to the north use the app too) that is the destination of the shipment.  Not every shipping vendor can ship to every destination, so we should modify the contents of the shipping vendor dropdown to reflect the destination.  Likewise, a change in the selected shipping vendor will also cascade down to the list of shipping options (think Overnight, 2 business day, parcel, etc.).  Some, but not all, shipping options allow the customer to purchase insurance in case of loss or require a signature at the destination for guaranteed delivery.  Finally, the cost of the shipment should be recalculated and displayed on the screen anytime the shipping selections are changed.

I can spot a couple different responsibilities in just that paragraph, plus a couple more down the line when it's time to actually submit the shipment.  Even this little screen has enough complexity in it that I wouldn't want to bundle all of the responsibilities into a single autonomous view.  So let's enumerate just the responsibilities from that paragraph and start thinking about how to assign these responsibilities to different classes.

  • Display and capture the currently selected shipment options
  • Respond to user events like selecting a value in the ComboBox's
  • Fetching the list of states
  • Fetching the list of shipping vendors for a given state or province
  • Fetching the list of options for a given state/province and vendor
  • Changing the dropdown lists
  • Enabling and disabling the checkbox's for purchasing insurance and requiring a signature
  • Calculate the shipping cost for the selected options
  • Update the cost textbox whenever the shipment options change

That's a fair amount of behavior and business logic for one little screen.  We know that we probably want to employ some sort of Humble View approach to split out some of the responsibilities from the Form class and into POCO classes that are easier to test.  I'm going to show three sample solutions of the shipping screen, each using a bit different approach to assigning responsibilities.

 

Interlude

The four friends mull over the looming fight with the forces of Lady de Winter as they finish off a fine cheese produced from the endless saddlebags of Aramis's manservant.  D'Artagnan  poses this question to the older musketeers:  "When I'm beset by a multitude of concerns in a single screen, what technique should I use to best each concern in turn?"  The three older musketeers ponder the question raised by their younger companion.  Finally, Athos speaks up.  "I would not concern myself with the simpler responsibilities of a screen.  I would first seek to eliminate the more complicated screen responsibilities by employing..."

 

The Supervising Controller

The goal of the Supervising Controller variant of Model View Presenter is to remove the more complicated screen scenarios that deserve more unit testing attention out of the view and into a separate Presenter class.  The Supervising Controller strategy takes advantage of the data binding support in WinForms for simple screen synchronization.  To that end, we'll create a simple class called Shipment that will be our Model in the MVP triad. 

    public class Shipment : INotifyPropertyChanged

    {

        private string _stateOrProvince;

        private string _vendor;

        private string _shippingOption;

        private bool _purchaseInsurance;

        private bool _requireSignature;

        private double _cost;

 

 

        public string StateOrProvince

        {

            get { return _stateOrProvince; }

            set

            {

                _stateOrProvince = value;

                fireChanged("StateOrProvince");

            }

        }

 

        public string Vendor

        {

            get { return _vendor; }

            set

            {

                _vendor = value;

                fireChanged("Vendor");

            }

        }

 

        // And the rest of the properties...

 

    }

The View itself simply has a setter that takes in a Shipment object and starts up the data binding. 

        public Shipment Shipment

        {

            set

            {

                // start up the data binding stuff

            }

        }

I'll talk about options for the Model in depth in a later post, but for now, let's say that Shipment is just a dumb batch of getters and setters.  Since I can't stand writing INotifyPropertyChanged interface implementations by hand, you'll probably want to codegen these Model classes -- again giving me even more reasons to keep the Shipment class dumb.

We've taken care of the actual presentation of the shipment data, so let's move on to more responsibilities.  There's no possible way that a screen should know how to calculate the shipping costs, and probably shouldn't know how to fetch the data for the dropdown selections.  Deciding whether or not a shipper and shipping option allows a user to purchase insurance or require a signature on receipt is business logic for the real domain logic classes, not screen logic that belongs in the screen.  Let's not particularly worry about how this stuff is implemented right now.  Let's just define an interface for all of this functionality (and a Data Transfer Object as well).

    public class DeliveryOptions

    {

        private bool _purchaseInsuranceEnabled;

        private bool _requireSignatureEnabled;

 

 

        public bool PurchaseInsuranceEnabled

        {

            get { return _purchaseInsuranceEnabled; }

            set { _purchaseInsuranceEnabled = value; }

        }

 

        public bool RequireSignatureEnabled

        {

            get { return _requireSignatureEnabled; }

            set { _requireSignatureEnabled = value; }

        }

    }

 

    public interface IShippingService

    {

        string[] GetLocations();

        string[] GetShippingVendorsForLocation(string location);

        string[] GetShippingOptions(Shipment shipment);

        void CalculateCost(Shipment shipment);

        DeliveryOptions GetDeliveryOptions(Shipment shipment);

    }

The IShippingService interface works on our Shipment class that we're binding to in the actual screen, as opposed to exposing primitive arguments.  When I was writing the sample code it seemed to me to be a simple way of interacting with the service because it cuts down on any data transformations between screen and service.  The CalculateCost(Shipment) method would also write the cost back to the Shipment object, cascading a corresponding change to the screen as the data binding updates the screen based on changes to Shipment.  It's probably worth noting that this IShippingService could just be a Facade class over the business logic specifically created for easier consumption by the user interface.  In the next chapter I'll take a different approach that exposes the underlying Domain Model classes for the shipping system.

At this point we're largely left with just responsibilities for changing the dropdown options and mediating between the View and the IShippingService.  That's where the ShippingScreenPresenter finally comes in to provide the missing functionality that goes beyond simple data binding, as well as coordinating user actions with the IShippingService.

    public class ShippingScreenPresenter

    {

        private readonly IShippingScreen _view;

        private readonly IShippingService _service;

        private Shipment _shipment;

 

        public ShippingScreenPresenter(IShippingScreen view, IShippingService service)

        {

            _view = view;

            _service = service;

            _shipment = new Shipment();

 

            // Since we're got the INotifyPropertyChanged interface on Shipment,

            // we might as well use it to trigger updates to the Cost

            _shipment.PropertyChanged += new PropertyChangedEventHandler(_shipment_PropertyChanged);

        }

 

 

        private void _shipment_PropertyChanged(object sender, PropertyChangedEventArgs e)

        {

            _service.CalculateCost(_shipment);

        }

 

        public Shipment Shipment

        {

            get { return _shipment; }

        }

 

        public void Start()

        {

            _view.Shipment = _shipment;

        }

 

        // React to the user selecting a new destination

        public void LocationChanged()

        {

            _view.Vendors = _service.GetShippingVendorsForLocation(_shipment.StateOrProvince);

        }

 

        // React to the user changing the Vendor

        public void VendorChanged()

        {

            _view.ShippingOptions = _service.GetShippingOptions(_shipment);

        }

 

        // React to the user changing the Shipping Option

        public void ShippingOptionChanged()

        {

            DeliveryOptions options = _service.GetDeliveryOptions(_shipment);

            _view.InsuranceEnabled = options.PurchaseInsuranceEnabled;

            _view.SignatureEnabled = options.RequireSignatureEnabled;

        }

    }

Since I've been claiming that this style of user interface structure improves the testability of the screen as a whole, let's take a look at what the unit tests might look like.  Here's the unit test for correctly enabling or disabling the insurance and signature checkbox's on the shipping screen after the shipping option changes:

 

        [Test]

        public void EnableOrDisableTheInsuranceAndSignatureCheckboxesWhenShippingOptionChanges()

        {

            MockRepository mocks = new MockRepository();

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

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

 

            ShippingScreenPresenter presenter = new ShippingScreenPresenter(screen, service);

 

            // Setting up the expected set of Delivery options

            DeliveryOptions deliveryOptions = new DeliveryOptions();

            deliveryOptions.PurchaseInsuranceEnabled = true;

            deliveryOptions.RequireSignatureEnabled = false;

 

            // Set up the expectations for coordinating both

            // the service and the view

            Expect.Call(service.GetDeliveryOptions(presenter.Shipment))

                .Return(deliveryOptions);

            screen.InsuranceEnabled = deliveryOptions.PurchaseInsuranceEnabled;

            screen.SignatureEnabled = deliveryOptions.RequireSignatureEnabled;

 

            // Perform the work and check the expectations

            mocks.ReplayAll();

 

 

            presenter.ShippingOptionChanged();

 

            mocks.VerifyAll();

        }

The first thing you might notice is that this is definitely an interaction based unit test.  That's not surprising since one of the primary duties of a Presenter is to mediate between the services and view.  In development with Test Driven Development / Behavior Driven Development, it's often advantageous to separate the responsibility for performing an action away from the decision to perform that action.  In this case, the real View enables the insurance and signature checkboxes when the Supervising Presenter tells it to enable or disable the checkboxes.  In other words, the Supervising Presenter is the mostly immobile queen bee, and the View is the mobile, but relatively brainless, worker bee.  In unit tests like the one above, we're largely testing that the Presenter is sending the correct signals to the View and service interfaces.

For another example, here's a unit test for recalculating the shipment cost as the selected shipping options change:

 

        [Test]

        public void UpdateTheCostWheneverTheShipmentChanges()

        {

            MockRepository mocks = new MockRepository();

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

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

 

            ShippingScreenPresenter presenter = new ShippingScreenPresenter(screen, service);

            service.CalculateCost(presenter.Shipment);

 

            mocks.ReplayAll();

            presenter.Shipment.Vendor = "a different vendor";

            mocks.VerifyAll();

        }

That wasn't that bad, now was it?  But wait, you ask.  Where's the actual logic for calculating the shipment cost?  For right now I'm just worried about the wiring of the screen itself.  Yes, this unit test covers very little ground, and it's not a "real" test, but I've created some level of trust that this particular linkage in the code does work.  I can now turn my back on the screen itself and test the actual ShippingService by simply pushing in Shipment objects and checking that the Cost field is correctly updated.  Not one single line of the shipping screen code needs to be present for any of that logic to be tested.  I hope it's needless to say that there really shouldn't be any leakage of domain logic into the screen code.  Real domain logic in views is just about the fastest way possible to create an utterly unmaintainable system.

 

Interlude

The four friends pondered Athos's solution in quiet contemplation in the state of contentment that only follows a fine meal.  "Wait," exclaims D'Artagnan, "You haven't told us how the View talks to the Presenter, and who creates who!  How should this work?"  Athos simply shakes his head and says "it's a long ride to Dunkirk, we'll talk more of this on the road."  (as in, I'll get there, just give me a couple more chapters - Jeremy).

 

How I Prefer to Work

Personally, I wouldn't order the work quite the way I showed above.  I like to start with either a screen mockup or maybe even the actual view.  If you start with the actual concrete view class, don't wire it up yet, and whatever you do, don't automatically implement the intended "IView" interface until you're done with the Presenter.  Sometimes I'll start by taking some notes or sketching out some UML or CRC models about the screen scenarios.  My next step is to encode the behavioral aspect of the screen in the Presenter.  I use RhinoMocks in place of both the View and whatever service interfaces the Presenter needs.  As much as possible, I like to define the methods and interactions of the Presenter with the services and view in a unit test body and just let ReSharper generate the methods on the dependencies.  Since we're strictly dealing with interfaces here, we don't have to break our flow with the Presenter to implement the services and view just yet.  As soon as the Presenter itself is fully fleshed out, I implement the IView interface on the real View and create an implementation for any of the service dependencies.

This probably isn't realistic for complex screens, but at least on simple screens it should become quite ordinary for a screen to just work the first time it's run in the UI -- assuming you unit tested all of the pieces individually.

 

Summary

I'd bet that Supervising Controller is probably the most commonly used Humble View architecture, but I don't have any figures at hand on that.  It still allows you to use the design time support to layout controls and even configure the data binding with the visual tools (but we're going to talk about options to data binding later).  My current project is using Supervising Controller (sans data binding), and I think it's largely where the sweet spot is.  I will use the other options at times though, and there are a lot of different variations on each of the other Humble Views, so we're not done yet.

Is this really worth doing?  I say yes, otherwise I wouldn't be doing it.  Let me put it to you this way, on the first project I used the Humble View (Passive View actually) approach, we saw a strong correlation between the bug count per screen and the unit test coverage for the code on that screen.  Screens that were driven with unit tests on the Presenter had many fewer behavioral bugs.  I'm talking it even farther on my current project by adding NUnitForms tests on the View to Presenter interaction, plus Fit tests on the actual screen behavior. 

If you're not a fan of interaction based testing, and using mock objects gives you an allergic reaction, don't worry.  I've got stuff for you too coming up. 

 

 

Conclusion

The four friends pondered the wisdom of Athos' approach while drinking their way through the rest of the wine from D'Artagnan's packs.  Suddenly, mighty Porthos clears his throat and...

 

To be continued in Part #3 - The Passive View Pattern

 

 


Posted Fri, May 25 2007 7:55 AM by Jeremy D. Miller

[Advertisement]

Comments

Nate Kohari wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Fri, May 25 2007 9:38 AM

This is a great series of posts! I'm a big fan of MVP via Passive View, and I've used it extensively, but it's helpful to read another take on it. I'm interested how far into the CAB you're going to delve -- SmartParts? Extension points? Dependency injection? Loose-coupled messages?

Keep them coming!

Jeremy D. Miller wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Fri, May 25 2007 10:01 AM

@Nate,

Let's see,

"SmartPart" -- right there I'm already shaking my head at CAB nomenclature.  I'll read up on it a bit and see if I think it's worth showing something

Dependency Injection -- Lot's of people are asking for this, and I think I made some disparaging remarks in the past about ObjectBuilder, so I'll definitely show what StructureMap can do instead.

Loose-coupled messages -- I've got an example of an Event Aggregator

jdn wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Fri, May 25 2007 12:50 PM

This is probably a silly question, but is there a specific reason why in the tests you call the view a screen and not a view?

Couldn't more complicated screens implement multiple views?

Wondering if there was a prescriptive (or other) reason for the terminological choice, or if that is just what you typed (so to speak).

Jeremy D. Miller wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Fri, May 25 2007 12:59 PM

@jdn,

Sloppiness?  I always call it View in my real code.  A complicated screen could easily contain multiple IView parts and/or multiple presenters.

Sorry, it's just what I happened to type

jdn wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Fri, May 25 2007 1:05 PM

Cool.  When I'm trying to really learn something, I tend to focus on every difference.

Great series BTW.  I've been reading everything about MVP I can get my hands on, and this really helps things come together.

Steve wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Sun, May 27 2007 8:49 AM

These posts are greatly appreciated, thanks for providing this to community.

I'm using MVP right now and every tidbit helps.  ie. I'm not using the INotifyPropertyChanged right now, and I'm trying to wrap my head around how I can implement this (I'm using a webform though, so not sure about the difference here)

Matthias Cavigelli wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, May 28 2007 6:39 AM

Thank you for the realistic example. The dependent dropdown lists are a common example of how business logic and complexity infiltrate the view.

It's also interesting to see where you divide between Winforms Databinding and custom code.

I'm looking forward to your post on Passive View.

Jeremy Wiebe wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Wed, May 30 2007 10:04 PM

I'll second all the comments about these being useful posts!  We're just now heading down the path of evaluating the Web Client Software Factory.  Our reasoning for evaluating it is that it forces us down the path of the patterns and does some hand-holding in applying those patterns because many of us are not very familiar with the patterns (yes, we're learning them but there's only so many hours in a day).  The other compelling reason is that the WCSF uses WF (Workflow Foundation) for the page navigation and that brings some really nice benefits in terms of the user being able to abort a "process" and return to that exact point as if they never left.    I'm not sure how you'd build that, but just thinking about it does not seem like a simple task to grow yourself.  (I'd compare that to a build vs. buy decision).

Oh, and hurray for having "State or Province"!   I'm one of those crazy Canucks!  :-)

Max wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Fri, Jun 1 2007 7:11 PM

I'd like to add my own voice to the many above congratulating you on this series :-).

However, am I right in thinking that there is a slight bug in the code above in that changing ShippingScreenPresenter._shipment.Cost results in a call to _shipment_PropertyChanged, which calls IShippingService.CalculateCost(_shipment), which updates the Cost of that shipment, which results in a call to _shipment_PropertyChanged.....

I've hit this kind of circular update loop a few times in my own apps, do you know of a clean workaround? My solutions in the past have involved defining a sort of transaction in which updates to the event triggering model object are done, and events to actually be fired are queued up until the transaction commits. If a change to a model property happens when a transaction is already on progress on the model, I don't raise the event. I'm not sure if this is the best solution however... would be interested in hearing your thoughts.

Jeremy D. Miller wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Fri, Jun 1 2007 7:38 PM

@Max,

Nice catch!  This isn't real code from a working app (obviously).  Yes it certainly would create a circular event.  I use pretty well exactly what you describe in these cases where an event causes an action which potentially raises the exact same event.  There's a pattern from messaging called the "Latch" that's basically what you describe.  I don't necessarily have anything better.  I'm including a little bit about that in the post on the Event Aggregator.

Of course, in this case you could beat it by removing Cost from the Model and pushing in the updated Cost through more of a Passive View approach.

ShawnD wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Tue, Jun 26 2007 2:33 AM

What class implements the IShippingService?

Jeremy D. Miller wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Tue, Jun 26 2007 5:31 AM

@ShawnD,

Just another class.  All I wanted to show was a separation of concerns for the shipping logic and data access from the Presenter.  In my systems IShippingService would be attached with an Inversion of Control tool (StructureMap).

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

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

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

John Rusk wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Sun, Sep 2 2007 11:52 PM

Jeremy,

Here's another way to avoid manually writting property change notification code:

www.agilekiwi.com/.../ClaytonsInterceptionDemo.cs

("documentation" is here:

dotnet.agilekiwi.com/.../claytons-interception.html )

Jeremy D. Miller -- The Shade Tree Developer wrote Build your own CAB #15 - MicroControllers
on Sun, Oct 21 2007 9:13 PM

After a bit of a hiatus and a fair amount of pestering, I&#39;m back and ready to continue the &quot;Build

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

Rob Kitson wrote Keeping UI construction DRY
on Fri, Jan 25 2008 2:47 PM

Keeping UI construction DRY

Kent Boogaart wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, Feb 18 2008 8:41 AM

Another way to fix the circular/recursive event problem is to properly honor the contract of the INotifyPropertyChanged interface. The PropertyChanged event should only be raised if the property actually changes:

public bool SomeProperty

{ get { ... }

 set

 {

    if (_someProperty != value)

    {

        _someProperty = value;

        OnPropertyChanged("SomeProperty");

    }

  }

}

PS. I know I'm late - just catching up on the BYOC series, and really enjoying it, Jeremy.

Jeremy D. Miller wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, Feb 18 2008 8:51 AM

@Kent,

But then I'd have to use INotifyPropertyChanged on my domain classes;-)  I'm perfectly willing to tilt the windmill and build my own screen synchronization that binds to POCO's instead.

The MicroControllers thing I use in place of data binding takes care of the latching for me.  OnChange events will not fire when the binding is being updated.

Kent Boogaart wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, Feb 18 2008 9:12 AM

@Jeremy

*confused* Your example already has a Shipment class that implements INotifyPropertyChanged. What I'm saying is that if you alter the implementation of Shipment to correctly honor the contract, you will avoid this problem without need of a latch.

And I'm curious as to why implementing INotifyPropertyChanged in your domain layer would be a bad thing. I typically have my domain layer support change notification so that binding directly to domain objects is possible. Makes things much easier, IMHO.

Jeremy D. Miller wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, Feb 18 2008 9:38 AM

@Kent,

All I meant was that in real life I do not use INotifyPropertyChanged. I did in this example, and the naive implementation is partially because I don't actually use it on projects.

"And I'm curious as to why implementing INotifyPropertyChanged in your domain layer would be a bad thing. I typically have my domain layer support change notification so that binding directly to domain objects is possible. Makes things much easier, IMHO."

This is funny, I'm having this exact same argument with Ward Bell at the moment.  My point of view is that INotifyPropertyChanged/IEditableObject/IErrorInfo and what else is noise code that detracts from the readability of my domain classes.  That stuff is infrastructure concerns that shouldn't show up in a domain model class.  It's also modifiability to me as well.  Modifying or adding a property, then tweaking the INotifyPropertyChanged implementation is friction to me.  You could beat it all with codegen, but I really don't want to have to codegen my domain model classes because I think that's a drag on productivity.

I might happily use INotifyPropertyChanged if I was using codegen'd DTO's for the Model.

I'm well aware that I'm the unusual one in the .Net world on this topic.  I'm bypassing data binding altogether in favor of my own MicroController strategy, and it's going smoother than my prior experiences with data binding.

I do cover a bit of this stuff in the section on "What's the Model?"

Kent Boogaart wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, Feb 18 2008 10:17 AM

Thanks Jeremy. I see what you were getting at now.

> You could beat it all with codegen, but I really don't want to have to codegen my domain model classes because I think that's a drag on productivity

I concur, which is why I put together a home-grown codegen solution in past projects which has saved me a *heap* of time. I have formalised this solution and am planning to release it soon on CodePlex.

It's basically codegen built right into VS. You change your template or input file, hit Ctrl-Shift-B and it's done. It assumes nothing about input format or template engine (comes with NVelocity support). The core of the product is done. The only thing I have left to do is add VS integration to avoid the need for manually editing project files.

Anyways, basically what I do is define a simple input file that defines each of my domain objects. Then I have an NVelocity template used to generate a partial class for each domain object. Works a treat. Not only can you do stuff like change notification easily, you can also do stuff like generate custom serialization logic (ie. implement ISerializable) to keep your domain serializing like a ninja, implement IEditableObject etcetera etcetera. And all without sacrificing maintainability or productivity.

Jeremy D. Miller wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, Feb 18 2008 10:22 AM

@Kent,

That sounds cool.  This is one of those scenarios where I'd like to play with compile time IL weaving to layer the extra stuff on sometime.

nblog wrote Tfs Spotlight – buduję własny CAB
on Tue, Mar 11 2008 7:07 AM

Od kilku miesięcy nic tu nie pisałem (oczywiście poza poprzednim nieplanowanym wpisem ). Jak łatwo się

Sunny wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Tue, Mar 11 2008 9:05 AM

Hi Jeremy, I was reading the code and I just wonder if you might have missed the code to set the Locations in the view (or I have mis-read it)? and if so, am I right that it should be after setting the Shipment in the _view (at the end of the Start method)?

Taking Ninject to new places | Ivan Porto Carrero wrote Taking Ninject to new places | Ivan Porto Carrero
on Tue, Apr 22 2008 12:36 AM

Pingback from  Taking Ninject to new places | Ivan Porto Carrero

江南白衣 wrote View to Presenter Communication(转)
on Sat, Aug 2 2008 7:40 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

rüya tabiri wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Wed, Nov 26 2008 12:24 PM

Thank you...

Miksu wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, Dec 1 2008 7:45 AM

Hi.

First of all, thank you for great posts. Hopefully someday you'll finish this series but in the mean time, the already available posts contain great deal of interesting information :)

I have a question about the supervising controller pattern. All the examples I've seen show the data binding between the view and the model as a read-only (1-way). What's your opinion on using 2-way connections between the view and the model? I'm creating a WPF application and it seems kind of pointless to direct all the user actions first to then presenter when I could talk directly to the model.

For example, I have a CustomerEditView. It contains about 10 textboxes where the user can write related information. In addition to that, the view has few buttons (delete customer, update customer, cancel). If I want to show interactive information when user is changing the data (for example "Name is too short"), with the 1-way connection I kinda have to implement "Changed"-methods into the presenter for every available textbox. I then end up with methods like FirstNameChanged, LastNameChanged, AgeChanged etc. etc. These methods are called by the view when for example FirstNameTextBox changes. This method then changes the value in the model and may present an error to the user if the new value isn't valid. Writing these feels really cumbersome.

So how about using 2-way data binding? This way I could delete all the Changed-methods from my presenter and just let the data binding provided by WPF to handle this stuff. Presenter would only contain the more complicated stuff, which in my case would be the handling of update, delete and cancel actions.

It's rather interesting to see that even Microsoft shows the data binding between the view and the model in the supervising controller -pattern in a WPF-application as a 1-way. msdn.microsoft.com/.../cc707873.aspx

So if I want to use 2-way data binding in a supervising controller, should I be prepared for angry people, saying that my take on the pattern is wrong?

Best regards,

Mikael

Jeremy D. Miller wrote re: Build your own CAB Part #3 - The Supervising Controller Pattern
on Mon, Dec 1 2008 8:12 AM

"So if I want to use 2-way data binding in a supervising controller, should I be prepared for angry people, saying that my take on the pattern is wrong?"

It's partially a case of "who cares what other people think"

In your case, I think you want to look at the Presentation Model pattern instead (the WPF team calls it Model - View - ViewModel).  PM is ideal for this kind of state machine screen thing you have.

Sam Gentile's Blog wrote On CAB and P and P
on Tue, Dec 2 2008 9:48 PM

I didn't want to have to write this post . I've been disapointed for well over a week about this and I've phoned Jeremy Miller twice to discuss my displeasure. A ways back, Ayende decides to bash the entire P&amp;P team at Microsoft and specifically CAB

Add a Comment

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