CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

May 2007 - Posts

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

  • Choose your own adventure! Where does "Build your own CAB" go next?

    Everyone,

    The "Build your own CAB" series has enjoyed a very warm reception and I thank you all for the compliments I've received over the last couple weeks.  Before I go on much farther with the series, I want to open the "story" prioritization up to you all to make sure we talk about the things you care most about before I run out of steam on this one.  I'm finishing up the Passive View pattern right after this, but after that I'll leave it up to you.

    Here are the topics I have in mind:

    • Assigning responsibilities to the Model View Presenter triad
    • Patterns of View/Controller communication
    • Presentation Model - a different take on Humble View's
    • Synchronization issues with the backend
    • What are the options for the Model?  (short)
    • Using the Notification Pattern.  Performing input validation in the Domain Model and connecting these errors to the screen elements
    • Pluggability -- tricks and examples for wiring together UI components with StructureMap
    • Event Aggregator -- coordinating events to disparate screen elements in a loosely coupled manner
    • Subcutaneous Testing
    • MicroController, a recipe for better screen element synchronization.  I've written a partial replacement for data binding that bakes in declarative screen element behavior and testability
    • Building an Application Shell -- I've got 3-4 different examples of building an ApplicationShell/ApplicationController to handle navigation and screen coordination
    • Driving WinForms through Fitnesse/StoryTeller tests.  What's worked for me, and what's bombed.
    • Applying NUnitForms (I'm an admin on NUnitForms, and it never gets the attention it deserves)

    If you've got a preference, just let me know.

     

    Thanks,

    Jeremy

  • Martin sends a little shot across MS's bow

    Martin Fowler on RubyMicrosoft.  Nothing I haven't heard or said or thought before, but still, it matters when a Martin Fowler says it.

    I'm going to (slowly and) carefully work up my thoughts on his post in some depth.  In the meantime, go read what Martin says and come back here and tell me what you think.  The 'Bliki' doesn't do comments, but The Shade Tree Developer does (and will as long as the CS spam filter + CAPTCHA do their thing). 

  • A Train of Thought - May 21-28, 2007 Edition

    Just some quick things I've jotted down over the last week and change.  But first, sigh...

    The CAB + P&P Brouhaha

    The bit of nastiness, or perceived nastiness, over the CAB and Patterns and Practices recent blogging has got to stop so we can get back to what should be a very valuable discussion.  Email and blog posts just aren't a great way to have an effective conversation.  Negative vibes just come through far too easily without actual human contact.  Body language and face to face contact would have stopped the unpleasantness in its tracks.  The role of the Patterns and Practices team and the appropriateness of the Composite Application Block are very useful discussions to have.  We need to be able to disagree, and even criticize, without getting personal.

    Dredging up six year old newsgroup posts to try to make one of the participants look bad is nothing but childish.  My God, 6 years ago *I* thought VB6 was the single best language on Earth, C++ developers must all be gods, Java developers were wussies for trying to abstract the database away, all data access should be through stored procedures, and this new UML thing was the best possible way to work through a design before starting code.

    Everyone, including me, repeat after me:

    • I am not my code.  A criticism of my code doesn't have to be a personal attack on me.
    • I am not the tools that I use.  A criticism of my tools shouldn't be construed as a personal attack on me.
    • I am not the programming language that I use

    Let's remember the lossiness of communication on the blogosphere and keep a thicker skin.

    In defense of CAB

    Actually, the very fact that so many smart people (Sam, Chris Holmes, and Bil Simser) came out in favor of the CAB *is* a big endorsement of its capabilities and usefulness -- so what do I know?

    CAB and the Roll Your Own vs. Off the Shelf vs. Not using a framework at all conversation

    Part of the blogging going on at the moment about the CAB and P&P team is around the neverending question to use a framework off the shelf or roll you own.  Let's make a few things very clear, I don't use the CAB, I do use MVP patterns quite successfully with a high degree of test automation, and I do not have to roll my own CAB to do so.  When I say "grow your own," I really do mean to simply grow what you need -- when you need it, as you need it.  For my apps, the CAB is severe overkill.  The problems that the CAB solves don't seem to be particularly hard to me anyway (can someone please write in and give an example of something hard that they think the CAB makes easy?  Seriously, I'm willing to be wrong about this).

    Somebody quizzed Ayende on why he thinks it's okay to rewrite the CAB but NHibernate is okay to use right off the shelf.  That's an easy one for me.  Tools that amount to "just something that you use" like NHibernate, or log4net (but I'm not letting them off the hook for the versioning and breaking API hell a couple years ago) are not intrusive.  You just use them when you need the service that they provide.  Tools and frameworks that are intrusive into your code, or even worse, require you to wrap your application around their opinionated structure are a different story altogether.  I'm thinking about frameworks like NEO, the current version of the Entity Framework (but they've promised to make the intrusiveness optional in a later release), CSLA.Net, and the CAB.  I'm not saying that I wouldn't ever use these tools, just that the bar for using them is much higher in my mind than something like NHibernate.  If I hit a project where CAB does exactly what I want it to do, and learning and applying it is faster than building my own, I'll do it (just as soon as I rip out ObjectBuilder & replace it with StructureMap ;-) ).

     

    Patterns & Practices

    For the record,here's my description of the P&P team (emphasis added for here, and some grammar corrected):

    The Patterns and Practices team is a little beacon of Agile light in the Microsoft sea.  Yes I do think that many of the P&P solutions aren't really all that great, but I want the P&P team to succeed.  A strong, visible P&P team benefits us greatly.  The P&P team is making it easier for me to use the techniques like Dependency Injection and TDD on client engagements.  That's a win.

    I know they're Agile, and I love that, but it's perfectly acceptable, and even desirable, to critique their work products.  There's no way we should just accept anything they, or anyone else for that matter, create without question.  I actually won't back down too far over the "working in a vacuum" remark.  They're a centralized framework team, and that's the trickiest type of development to get right.  They're not dogfooding their own stuff inside of a real application project.  Yeah, they get feedback from clients, but it's not the same.  In general, I think splitting application teams from the framework builders is always dangerous.  It's dangerous inside of a single enterprise, and even more so for an entire development community.  No matter how talented the P&P team is, and they certainly are, they're working at a disadvantage compared to someone who's harvesting a framework.

    I do wish the P&P team would be a little more receptive to OSS tooling, or at least talk about OSS tools on their website.  Especially when they're writing tools and using techniques pioneered by OSS tools or other development communities that predate their own work.  I think it's great that they adopted Dependency Injection and publicized the pattern, but it would be nice if they'd at least admit that they didn't invent the concept and mention the other tools. 

    No, I don't think I can build a better CAB

    Not going to happen, and it's not worth the time to even try.  Yes, if you ask me in an unguarded moment I might admit that I'm cocky enough to think that I could build a better CAB, but it's not high on my list of priorities.  My argument against using the CAB revolves around the idea that I do not need any kind of elaborate framework for WinForms development.  The easy stuff is easy, and the hard stuff tends to be very specific to each application.  I want the semantics of the screen navigation and coordination to be expressed in terms of the application domain, not in language like "SmartParts."

    But if I were to even flirt with the idea of "ok smart guy, let's see you do something better..." it would be with IronRuby when that becomes a tad more mature (like, actually released as a download) -- and that's mostly to have a real thing to do with Ruby.  I think somebody, either one of us or the P&P team, could make a CAB-killer by using either embedded DSL's in Ruby or some of the more advanced C# 3 features.

    And if it did come down to an attempt to write a better CAB, I don't see that as being even slightly irresponsible.  The CAB isn't the penultimate tool, and the P&P team doesn't have a complete monopoly on innovation.  Diversity is good.  Innovation is good.  I don't have to fall in line and use whatever technique or tool MS spits out if I think there's a better way.

    I do think that the contrib projects that Bil Simser was announcing for CAB & EntLib are exactly the right thing to do for these tools, and I was glad to see it.

     

    That's fine for you, but what about my guys...

    In the whole CAB thing I heard several remarks that basically went:  "that's fine for Ayende's and Jeremy's, but average developers can't roll their own."  The assumption being that developers that aren't talented or experienced enough to do Model View Presenter are going to be able to use the CAB effectively.  Two points:

    1. If you understand the underlying patterns, you are much better equipped to bypass the CAB
    2. You'll be much more effective using the CAB if you understand the underlying patterns first.  Tools are generally going to be easier to use when you understand why the tools are built the way that they are and what they're trying to accomplish.

    In the end, you better be studying the patterns regardless.  As soon as I get over a nasty hump early this week, I'll get cracking on my "Build your own CAB" series again to help in this regard.

     

    Automated tests are like push pins

    You know, some code is really easy, and it's awfully tempting to forgo testing that code.  It's still a mistake, because a test does more than check that the code works as you write the code.  It also pins down that code.  An automated test puts a stake in the ground that says "this should work like that, and if it stops working like that, I'm gonna throw a fit."  A set of automated tests lets me turn my back on a piece of code with the confidence that comes from knowing that anything that the behavior of my code won't get hosed by other changes without some warning.

     

    First, finish what you started

    Done, done, done.  I think you should take the attitude as a team that you get zero points for any work until you have something that's completely ready to ship.  That means working a feature from a gleam in the customer's eyes all the way through deployment scripts before you move on to the next piece of work.  Otherwise you just have two features in an intermediate stage with nothing ready to ship.  More importantly for this little rant, I want to finish out a user story at least to the point where I have those automated tests to act as a push pin before something else comes along and destabilizes the previous code.  Life's hard enough without getting screwed by somebody else's work.

     

    The Power of Osmotic Information

    At the DevTeach Pair Programming session the presenters showed some pictures of their work environment.  Other than substituting Space Invaders wall decorations for Jeffrey Palermo's gigantic Texas A&M banner (shudder, I'm a Rice grad), it looked a lot like our old office in Austin.  Basically, one long table in the center of a single room with everyone, and I do mean everyone, sitting around the table.  All conversations happen in the room.  Somebody across the room gasped "that's not what Joel says!"  To which I immediately yelled out "Joel is wrong!"  If you haven't seen it, Joel Spolsky published a checklist of his 12 questions that any good team in the Joel universe needs to answer in the affirmative.  One of his 12 points is that each developer gets his own office with a closed door so they can work in blissful silence without distraction.

    The noise isn't really that bad.  You're concentrating on your work and/or your pair.  It's really easy to block out other people when you need to.  Besides, it's just much more fun than the utter isolation of cubes or offices.

     

    Jeremy's take on the Joel Test

    Just for fun, here's my review of his list:

     

    1. Do you use source control? -- Oh lord, I hope so.  That's right up there with wearing sunscreen out to the beach
    2. Can you make a build in one step? -- 2 for 2.  Absolutely necessary for frictionless work.
    3. Do you make daily builds? -- Not good enough.  Daily builds are far better than no builds, but I'd rather have fullblown Continuous Integration going far beyond a simple daily compile.  Better traceability, causality, feedback
    4. Do you have a bug database? -- Yes, but you *can* do it in a very lightweight manner 
    5. Do you fix bugs before writing new code? -- Amen.  See the above on "finish what you started"
    6. Do you have an up-to-date schedule? -- You better not go into cruise on this one.  Planning never stops because you're learning things about the work as you go and priorities will change
    7. Do you have a spec? -- I agree in principle (surprise), but I disagree with Joel on the form of those specifications.  Requirements?  Heck, yes.  Word doc, hell no!  More on this later.
    8. Do programmers have quiet working conditions? -- See the osmotic information section.  This is the wrong question.  Do the programmers have a comfortable working area that facilitates collaboration?
    9. Do you use the best tools money can buy? -- Yeah, but you know that I think the answer is often OSS tools, so it's not just the money.  I will not code without ReSharper, naked VS.Net is just too painful.
    10. Do you have testers? -- I think it's absolutely insane how many organizations and teams do not have embedded testers on the development team.  It's irresponsible.  I'd go farther than Joel.  I want the testers completely embedded into the development process, not just swooping in at the end of the waterfall.
    11. Do new candidates write code during their interview? -- That's an awfully fast way to separate wheat from chaff
    12. Do you do hallway usability testing? -- No opinion, as long as I have plenty of user feedback, I'm happy.

    Nevermind, I agree with more of it than I thought.  I think he missed some big things (effective test automation, organized/formalized iteration management, lots of feedback loops, customer involvement), but I'm getting drowsy and I just don't have the requisite 'nads to do the "Jeremy Test."

    My advice vis a vis the Joel Test?  Again, there are no smart guys, only us.  Make up your own mind and fit your practices to your project.  The smartest thing you can probably do is just to constantly ask yourselves "if I could make one single improvement, what would it be?"

     

    Important Advice

    To all you youngsters out there, if anyone ever offers to let you check in first and then handle any ensuing merge conflicts, the answer is always YES! 

     

    It sucks being the one truck guy

    You know that awful phrase "what if you get hit by a bus, what do we do?"  Right now on my project I'm the "one truck guy."  It sucks.  I'm trying hard to offload some stuff and spread the understanding of the system, but it takes time.  I've got a team now (or I've got a handful of people invested enough in the project to make a standup worthwhile) , and it's actually a cool thing just to have a team instead of flying solo, but everyone else has a narrow purview of the work. 

    Specialization sucks.  Specialists can barely talk to one another.  Teams with redundancy in skills and knowledge are easier to work in, and work much more collaboratively, IMHO.

     

    Whatever it is, do it together

    Look, I like to put the headphones on and go heads down as much as the next person.  I'm one of those people who likes complete quiet to concentrate fully, but that's a local optimization for my personal productivity -- and we know that local optimizations are a fallacy.  No matter what the activity, if you're doing something that creates knowledge, be it design, API, build, or analysis knowledge, do the work together in a collaborative manner.  Yes, you're using more people to perform that particular task, but you might be saving much more time later because the participants have more knowledge by participating that they could ever glean after the fact from emails or specifications.

     

    CodePlex getting Subverted

    I think the recently announced Subversion support on CodePlex is a great thing.  I've got to run it by Jeffrey & Josh first, but I'm going to think pretty seriously about moving StructureMap off of SourceForge and over to CodePlex.  I'm not that wild about SourceForge.  It has everything you could ever possibly want, but it just feels too Unix-ey to me.

    Ok, nevermind.  I went and researched it a bit.  The SVN support sounds a little dodgy, and CodePlex feels slow and clunky to me (not that SourceForge is all roses, but it's familiar).  I'll wait and see.

  • What do you use to incorporate JSUnit tests into a NAnt build?

    Anybody got some good tips, or a working NAnt task for this that they like?  I use a slightly modified version of the JsUnit 2.1 TestRunner, but it would be pretty easy to convert to something else.

     

    Thanks in advance. 

  • 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

     

     

  • Build your own CAB Part #2 - The Humble Dialog Box

    When last we left our hero, D'Artagnan was chasing the evil Lady de Winter across the breadth of France trying to intercept her on her dastardly mission when he found himself beset by disparate responsibilities within the tight confines of a single autonomous view with no room for sword play.  D'Artagnan, being a perspicacious young man, quickly sees a way to separate the numerous concerns he's facing by opening his attack with...

    The Humble Dialog Box 

    I'd say the very first concept to grasp in software design is separation of concerns.  Divide and conquer.  Eat the elephant one bite at a time.  Learning how to decompose a bigger problem into a series of approachable goals.  I'd rather work serially on a screen by completing one simple task before moving onto the next instead of working with all aspects of a screen in parallel.  Division of responsibility for easier programming is a major consideration by itself, but there's another piece of motivation almost as important.  Because user interface code can be very complex to debug and is prone to change based on user experience, I really, really want to extend granular unit testing with automated tests as far into the presentation layer as I possibly can. 

    Traditionally, user interface code has appeared to repel all but the most serious attempts at test automation.  Automated testing against UI code was just flat out deemed too much work for the gain.  That equation has changed over the last several years with the rise of architectures inspired by The Humble Dialog Box from Michael Feathers. 

    Here's the canonical example of the Humble Dialog Box I use to explain the concept.  Say you have a user screen for some sort of data entry.  You have a requirement that reads something like:

    If the user attempts to close the XYZ screen without saving any outstanding changes, a message box is displayed to warn the user that they are discarding changes.  If the user wishes to retain the outstanding work, do not close the screen.  The message box should not be shown if the data has not been changed.

    It's not that complex of a requirement really, but it's the kind of thing that makes a user interface client easy and convenient to use.  We want this code to work.  The code for it might look like this:

            private void ArrogantView_Closing(object sender, CancelEventArgs e)

            {

                // Let's not worry for now about how we figure out the screen has unsaved data

                if (isDirty())

                {

                    bool canClose = MessageBox.Show("Ok to discard changes or cancel to keep working") == DialogResult.OK;

                    e.Cancel = !canClose;

                }

            }

    That code really isn't that complex, but let's think about how we could automate a test for this requirement to run within our regression test suite.  That little bitty call to MessageBox.Show() and the modal dialog box that results is a serious pain to deal with in an automated test (it is possible, and I've done it before, but I'd strongly recommend you keep reading before you run off and try it).  Observing the UI getting closed or not is also tricky, but I think the worst part is that to test this logic you have to fire up the UI, navigate to the screen, change some data on the screen, then trigger the close screen request.  That's a lot of work just to get to the point at which you're exercising the code you care about.

    Now, let's rewrite this feature as a "Humble" view, but before I show the new code, let's talk about the Humble view philosophy.  The first thing to do is to put the view on a diet.  Any code in a WinForms UserControl or Form is almost automatically harder to test than it would be in a POCO.  A Humble view should be the smallest possible wrapper around the actual presentation code.  Going farther, I don't want implementation details of the view mechanics to leak into other areas of the code, so I want to hide the View behind a POCO-ish interface.  All that being said, the abstracted interface for our View could look like:

        public interface IHumbleView

        {

            bool IsDirty();

            bool AskUserToDiscardChanges();

            void Close();

        }

    The view is also "passive," meaning that it doesn't really take any actions on its own without some sort of stimulus from outside the view.  I'll discuss handling user events in depth in a later chapter, but for now let's just say that the view simply relays user input events to somewhere else with little or no interpretation. 

    One of the goals of a Humble view is to separate responsibilities.  As in most designs, we want to assign different responsibilities to different areas of the code.  In this case, we want to pull behavioral logic out of the view and into non-visual classes.  If we put the view itself on a diet and pull out anything that isn't directly related to presentation, that extra code that implements things like behavior and authorization rules has to go somewhere.  In this case we're going to move those responsibilities into a Presenter class:

        public class OverseerPresenter

        {

            private readonly IHumbleView _view;

     

            public OverseerPresenter(IHumbleView view)

            {

                _view = view;

            }

     

            public void Close()

            {

                bool canClose = true;

                if (_view.IsDirty())

                {

                    canClose = _view.AskUserToDiscardChanges();

                }

     

                if (canClose)

                {

                    _view.Close();

                }

            }

        }

    In particular, look at the Close() method.  Some user event causes a call to the OverseerPresenter.Close() method.  Inside this method we check the "dirty" state of the IHumbleView member and potentially ask the user to discard changes before proceeding to close the actual view.  It's just about the exact same code, only now we can write an automated unit test to express this logic -- with just a little help from our good friend RhinoMocks.

        [TestFixture]

        public class OverseerPresenterTester

        {

            [Test]

            public void CloseTheScreenWhenTheScreenIsNotDirty()

            {

                MockRepository mocks = new MockRepository();

                IHumbleView view = mocks.CreateMock<IHumbleView>();

     

                Expect.Call(view.IsDirty()).Return(false);

                view.Close();

     

                mocks.ReplayAll();

     

                OverseerPresenter presenter = new OverseerPresenter(view);

                presenter.Close();

     

                mocks.VerifyAll();

            }

     

            [Test]

            public void CloseTheScreenWhenTheScreenIsDirtyAndTheUserDecidesToDiscardTheChanges()

            {

                MockRepository mocks = new MockRepository();

                IHumbleView view = mocks.CreateMock<IHumbleView>();

     

                Expect.Call(view.IsDirty()).Return(true);

                Expect.Call(view.AskUserToDiscardChanges()).Return(true);

                view.Close();

     

                mocks.ReplayAll();

     

                OverseerPresenter presenter = new OverseerPresenter(view);

                presenter.Close();

     

                mocks.VerifyAll();

            }

     

            [Test]

            public void CloseTheScreenWhenTheScreenIsDirtyAndTheUserDecidesNOTToDiscardTheChanges()

            {

                MockRepository mocks = new MockRepository();

                IHumbleView view = mocks.CreateMock<IHumbleView>();

     

                Expect.Call(view.IsDirty()).Return(true);

                Expect.Call(view.AskUserToDiscardChanges()).Return(false);

     

                // No call should be made to view.Close()

                // view.Close();

     

                mocks.ReplayAll();

     

                OverseerPresenter presenter = new OverseerPresenter(view);

                presenter.Close();

     

                mocks.VerifyAll();

            }

        }

    So I know what you might be thinking, what have I really gained here?  Let me try to answer this:

    • Orthogonality.  We've moved behavioral logic out of the actual view.  We can change the presentation or the behavior independently.  That is a big deal. 
    • The screen behavior is easier to understand.  I'm going to argue that this is a case of Reg Braithwaite's Signal to Noise Ratio in code (basically, expressing the intent of the code with little code that isn't directly related to the intent).  When I want to understand the screen behavior, that behavior is the only signal I care about.  Seeing (object sender, CancelEventArgs e) everywhere in the middle of the behavioral code is noise.  The converse is true as well when I'm working on the presentation itself.
    • The screen behavior is easier to test and modify.  That's enough by itself to justify the Humble View style.  What if this closing behavior changes tomorrow with a requirement to set a user preference to never ask users to discard changes?  If I'm working in a Humble View style, I can probably make that screen behavior change completely, including unit tests, in the Presenter class by itself without ever having to fire up the user interface until the very last sanity check.  Verifying little behavior changes with NUnit is a far, far tighter feedback cycle than doing the save verification by firing up the user interface and doing the manual input steps necessary to exercise the functionality.  Tight feedback cycles == productivity. 
    • By extending the reach of granular and automated unit tests farther into the potentially complex user interface code, we can drastically slow down the rate of screen defects getting through to the testers.  If nothing else, we can knock down all the common uses of the user interface quickly through tests to give the testers more time to break the application with edge cases and exploratory testing.

     

    An astute reader will note that we didn't write any unit tests for the View.  I'll show an example in later chapters of testing the View itself, but the philosophy in general is to make the hard to test view code so simple as to be reliably verified by inspection alone.  I.e., you should make the View code so simple that it's almost hard to screw it up. 

     

    A Taxonomy of Humble Views 

    Arguably the first Humble View is the original Model View Controller architecture handed down, as basically everything good in software developer seems to be, from the Smalltalk community.  As I've mentioned before, you can read about the evolution of the Model View Controller (MVC) pattern and the formulation of the Model View Presenter (MVP) patterns that we're mostly talking about in this series as user interface toolkits changed.

    D'Artagnan's masterful implementation of the Humble Dialog Box vanquishes his foes, but he knows he'll need trusted companions now that the evil Lady de Winter surely knows he is in pursuit.  Fortunately, D'Artagnan's trusty three companions are riding hard to join him.  D'Artagnan smiles to himself and imagines his friends coming around the bend in the road:

    1. Supervising Controller -- I'm here to help the View with the harder cases!
    2. Passive View -- I only do what I'm told
    3. Presentation Model -- Just do what I do

    D'Artagnan sees dust rising in the air, a traveler is coming...

     

    To be continued in Part 3:  Supervising Controller

       

    QUICK NOTE:  I showed the MessageBox stuff happening as a consequence of calling a method on the IView interface.  In the past I've also used some sort of IMessageBoxCreator interface to create message boxes directly.  There are advantages either way.

  • New .Net group in Westchester (NY) & Fairfield County (CT)

    http://www.fairfieldwestchester.net/

    Cool, just found out about the new group from a commenter.  Of course the first talk is on an inferior (read not StructureMap) IoC tool, but it's always good to see how other people do things.

    I promise that I will not heckle the Spring guys.

  • Build your own CAB Part #1 - The Preamble

    Yesterday I made a somewhat unsubstantiated claim that you simply don't need the Composite Application Block (CAB) to build nontrivial WinForms user interfaces in a maintainable fashion.  I claimed that mere mortal developers can master the underlying design patterns in the CAB and pick up a better Inversion of Control/Dependency Injection tool to organically grow an application structure that meets the specific needs of that application.  I even think that mere mortals can do this as or more efficiently as they can by utilizing the very generalized CAB.  To try to substantiate that claim, and because there seemed to be enough interest to warrant this series, I'm going to convert my WinForms patterns talk from DevTeach into a series of blog posts to demonstrate some design strategies for creating maintainable WinForms code.  Even if you're going to stick to the CAB (and that is a valid choice), I can hopefully add to your ability to use the CAB by exploring the very same patterns you'll find lurking underneath the covers in the CAB.  If you like the way the CAB does something better than the ways I present, please write in and say so.

    One of my favorite authors is Alexandre Dumas, author of the Three Musketeers books and the Count of Monte Cristo.  The Three Musketeers was the soap opera of its day, written in installments as a serial in whatever passed for magazines in those days.  Likewise, I'm going to try to dribble these posts out in little installments.  Basically the size of post I can write in a single sitting on the train ride from and to work.

    Note on terminology -- I'm a card carrying Fowlbot, so I'm using the terms set forth in Martin's forthcoming book on enterprise design patterns.

    It's just the User Interface right?

    "Just" the user interface?  I haven't seen this so much lately, but earlier in my career there was a definite attitude that User Interface (UI) programming was simple, grunt work -- unworthy of the attention of the serious developer.  In my mind I always think of the line "Just pick it up" from Caddyshack, or Kramer extolling Jerry to just "write it off."  That's a dangerous attitude because user interface code can easily be much more complex than the server side code in many systems.  It's worth spending some mental cycles on the design and structure of the UI code.  Here's why:

    • Creating user interface code is time intensive.  Not just in terms of the initial coding, but in my experience UI code generates the most defects and hence takes the most time to fix bugs.  We can cut down the defects by extending unit testing as far into the user interface code as possible.  TDD opponents often use the UI as an example of code that just can't be tested.  They're wrong, but UI testability d