Build your own CAB #13 – Embedded Controllers with a Dash of DSL

Start with http://andersnoras.com/blogs/anoras/archive/2007/07/04/i-m-coming-down-with-a-serious-case-of-the-dsls.aspx and come back.

Just to continue the world’s longest run on sentence.  Before I start, here’s the table of contents for the “Build your own CAB” series:

  1. Preamble
  2. The Humble Dialog Box
  3. Supervising Controller
  4. Passive View
  5. Presentation Model
  6. View to Presenter Communication
  7. Answering some questions
  8. What’s the Model?
  9. Assigning Responsibilities in a Model View Presenter Architecture
  10. Domain Centric Validation with the Notification Pattern
  11. Unit Testing the UI with NUnitForms
  12. Event Aggregator
  13. Rein in runaway events with the “Latch”
  14. Embedded Controllers with a Dash of DSL (This Post)
  15. MicroControllers – Forthcoming
  16. Subcutaneous Testing – Forthcoming
  17. Creating the Application Shell – probably a couple posts
  18. Wiring the Components with an IoC tool – Forthcoming

Why is this post necessary?

Why, you might ask, are you writing a post on what amounts to a “ViewHelper?”  One simple reason – View’s can easily become absolutely massive blobs of code.  Any chance to move a cohesive set of screen responsibilities into another class should serve to make the View itself simpler, and that’s all this post is about.  Plus, breaking a View’s behavior into multiple, cohesive classes can potentially lead to reuse opportunities for the little Embedded Controller classes.

For much of the last three years I’ve worked with a lot of legacy code over a half-dozen different codebase’s.  All of them, to be charitable, were less than ideal in quality and structure.  If you ask me what the single biggest flaw or problem across all of these codebase’s my answer would be near automatic — long classes and long methods.  What I continuously see is code stuffed into modules until the modules are coming apart at the seams. 

Come to think of it, my current project is about 95% greenfield code so far.  Come Thanksgiving time when it’s my turn to say what I’m thankful for my answer might just be “I’m thankful for getting six months of working on a greenfield project.”

Embedded Controller

Again, I’m not a sanctioned patterns naming body, but the term “Embedded Controller” is my name for nonvisual classes that help a View control some distinct part of it’s behavior.  The first example that comes to my mind is from a WinForms project that used a 3rd party grid (not a vendor on the CodeBetter friends list by the way).  The grid control needed a lot of consistent help and infrastructure code around it to implement the behavior we needed (little things like sorting and paging).  We quickly discovered that additional screens needed the exact same bootstrapping code, so the obvious answer was to extract that “grid helper” into it’s own reusable class.  We were using a pretty strict Passive View approach, but even so, we didn’t want the Presenter’s tied that tightly to the screen mechanics.  Instead, the new GridHelper class was just something that the View controls used internally.  After the third screen with the grid control, development suddenly went faster. 

To differentiate Embedded Controller classes somewhat from the Presenter, here’s the attributes of an Embedded Controller:

  • Nonvisual class used by a View to implement some of the View behavior.  I guess in
  • Completely encapsulated within a View.  There is no sign of the Embedded Controller in a View’s publicly facing interface.
  • Embedded Controller’s are happily aware of the actual, concrete UI widgets.  The Embedded Controller class “knows” about buttons and checkbox’s and the nasty 3rd party grid that you’re being forced to use.
  • Very limited in scope.  An Embedded Controller provides classical controller functionality for a very specific part of the screen

 

My advice for taking advantage of Embedded Controller’s is threefold:

  1. Look for common UI coding tasks within a system and look for opportunities to encapsulate some screen mechanics in reusable pieces.  This is just another exercise in eliminating duplication.
  2. Split up any View class that gets too big.  I might have left the impression in earlier posts that the View code is somehow exempt from the normal coding standards because we’ve made it “simpler” now.  Code quality matters everywhere, and especially in areas of the code that are likely to change over time – like View’s.  Even with a Passive View architecture a complex screen will almost inevitably lead to complex code in the View.
  3. Pulling out an Embedded Controller might be an easy way to extend unit testing deeper into the View.  This won’t always be true, but a “POCO” embedded controller class can often be quite easy to unit test inside vanilla xUnit tests without resorting to anything exotic like NUnitForms.  There is some widget behavior that only functions when a Form is visibly displayed, but a lot of behavior can be tested just by instantiating UI widgets directly within a unit test.  One way or another the UI widget stuff is nothing but CLR classes.

 

Sample:  The Control State Machine

Here’s a scenario from my current project that I bet all of us have dealt with a few times over.  We have a Trade screen that has seven different states depending upon whether you’re creating or reviewing a Trade.  The various user actions available on the screen differ from state to state.  As the screen changes state either upon opening the screen or a result of user actions while it’s open we need to enable/disable and show/hide different screen elements.  The screen started simple, so I just coded specific methods at first to enable or disable bits of the screen.  Fast forward a couple of weeks and the behavioral logic had exploded (funny how that happens when you actually get to talk to the end users).  Unsurprisingly, the code in the Presenter and View had become hairy, plus the screen had way too much flicker for that matter. 

Before I show any code, let’s be pretty clear that this code is not very optimized or even very powerful.  All I want to talk about is the concepts and structure of the design irrespective of performance.

At least in concept, the solution was pretty simple.  Move that logic into a state machine construct.  Since we already had a full set of regression tests against the UI screen itself, I felt pretty safe making the changes.  All I did was create a class called “ControlState” that’s nothing but a collection of Control’s to display and enable for a particular screen state.  ControlState has a method called Activate() which simply loops through its internal collection to enable and show the configured controls (it’s not shown but the call to Activate() is wrapped in SuspendLayout() and ResumeLayout()). 

 

        public class ControlState
        {
            private List<Control> _displayedItems = new List<Control>();
            private List<Control> _enabledItems = new List<Control>();
 
            public void ShowControls(params Control[] controls)
            {
                _displayedItems.AddRange(controls);
            }
 
            public void EnableControls(params Control[] controls)
            {
                _enabledItems.AddRange(controls);
            }
 
            public void Activate(ControlStateMachine<T> machine)
            {
                machine.LevelSet();
 
                foreach (Control item in _enabledItems)
                {
                    item.Enabled = true;
                }
 
                foreach (Control item in _displayedItems)
                {
                    item.Visible = true;
                }
            }
        }

As you can probably guess, there’s a second class that aggregates all of the configured ControlState’s and Control’s called ControlStateMachine<T>, where T is an enumeration of the possible states.  Here’s a little bit of its implementation. 

 

        private readonly Control _parent;
        private readonly IScreenBinder _binder;
        private List<Control> _displayedItems = new List<Control>();
        private List<Control> _enabledItems = new List<Control>();
        private Dictionary<T, ControlState> _states = new Dictionary<T, ControlState>();
        private T _currentState;
 
        public ControlStateMachine(Control parent, IScreenBinder binder)
        {
            _parent = parent;
            _binder = binder;
        }
 
        public void SetState(T stateKey)
        {
            _parent.SuspendLayout();
 
            _states[stateKey].Activate(_binder, this);
            _currentState = stateKey;
 
            _parent.ResumeLayout();
        }

The View itself just calls ControlStateMachine.SetState() to configure itself.

Now, for the cool part.  Here’s a somewhat obfuscated version of our code that defines the state machine inside the View.* 

        private void configureStateMachine()
        {
            _stateMachine = new ControlStateMachine<TradeDetailState>(this, _binder);
 
            _stateMachine.OnStateChangeTo(TradeDetailState.Creation)
                .Show(createTradeButtonsPanel)
                .Enable(status1CheckBox, status2CheckBox, status3CheckBox, externalTradeIdTextbox);
 
            _stateMachine.OnStateChangeTo(TradeDetailState.Review)
                .Show(updateTradeButtonsPanel)
                .IsReadOnly()
                .Enable(
                    editTradeButton, 
                    status1CheckBox, 
                    status2CheckBox, 
                    status3CheckBox, 
                    externalTradeIdTextbox, 
                    cancelTradeButton);
 
            _stateMachine.OnStateChangeTo(TradeDetailState.ReviewDirty)
                .Show(updateTradeButtonsPanel)
                .IsReadOnly()
                .Enable(
                    undoButton, 
                    status1CheckBox, 
                    status2CheckBox, 
                    status3CheckBox, 
                    submitTradeChangesButton, 
                    externalTradeIdTextbox, 
                    cancelTradeButton);
 
            _stateMachine.OnStateChangeTo(TradeDetailState.Edit)
                .Show(updateTradeButtonsPanel)
                .Enable(externalTradeIdTextbox, cancelTradeButton);
 
            _stateMachine.OnStateChangeTo(TradeDetailState.EditDirty)
                .Show(updateTradeButtonsPanel)
                .Enable(undoButton, submitTradeChangesButton, externalTradeIdTextbox, cancelTradeButton);
 
            _stateMachine.OnStateChangeTo(TradeDetailState.Cancelled)
                .Show(updateTradeButtonsPanel)
                .DisableEverything()
                .IsReadOnly();
 
            _stateMachine.OnStateChangeTo(TradeDetailState.History)
                .Show()
                .DisableEverything()
                .IsReadOnly();
        }

If you haven’t seen this kind of syntax before, it’s what Martin Fowler (a real patterns naming authority) has christened Fluent Interface.  Why, oh why, did I go to the extra trouble of making a Fluent Interface instead of just defining the state machine by filling up the collection state (and let’s be clear, it is a little more work)?  Because I thought it would make a good blog post wanted to create Domain Specific Language in the code to make the code easier to understand.

 

That’s Not Really a DSL!

Unfortunately, in my opinion, the .Net community is fixated on graphical Domain Specific Language’s (DSL) that revolve around yet more code generating visual tooling.  There’s a complete other side to the DSL’s however.  Another alternative is lexical languages which could be either internal/embedded or external to the language, with the pro-lexical argument being something like “people can read English you know.”  I’m not particularly enamoured of creating my own programming language and interpreter, so my particular area of interest right now is in creating embedded DSL-like syntax’s inside existing languages.  Granted, C# is very limited in this respect compared to other languages, but we can still achieve some useful gains with Fluent Interface coding. 

We’re about to get IronRuby and C# 3 as fullblown CLR languages.  Both languages, and especially IronRuby, are far better suited for internal DSL’s than C# 2.0.  The Ruby hype seems to be 9/10′s Rails, but the stuff that ThoughtWorks and others are doing with expressive DSL development in Ruby might turn out to be the real value proposition behind Ruby.

So is my little ControlStateMachine a DSL or just an API?  Running it through the Is It a DSL or an API Checklist, the answer is probably no, but the real value is simply an expressive AP.  The real goal (or enabler) is to move toward coding syntax’s and API’s that speak clearly in the semantics of the problem domain.  The general idea is that the correctness, or intent, of the code should become much more readily verified through simple inspection.  Ideally, you could move to the point where you are able to show your business logic code to the actual business users.  There will still be plenty going on behind the scenes, but they don’t need to see that.

 

David A. Black has a good post on Domain Specific Language that I’d recommend for a jumping off point.

I haven’t delved deeply enough yet, but Boo sounds like a good way to create lexical DSL’s in .Net today.

 

* It’s obviously a screen for capturing a Trade, but since half of the developers in New York seem to be working on a similar project at any given time, I’m not too concerned about publishing this.

About Jeremy Miller

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

    Complicated dialogs (containing hundreds of controls) usually have LOTS of code related to intercontrol dependency. E.g. on some CheckBox’s Checked event we want to do lots of things – not only enable/disable/hide/show other controls but also change their values, refill combos/grids/lists, etc. And when enabling/disabling/hiding/showing – we want to take into consideration complex logical conditions containing not only some properties of some controls but “external” data as well (e.g. permissions of current users, some app.settings etc). So I wonder if your configureStateMachine() approach is capable of handling such complex scenarios? I can’t even imagine how can I separate all this mess into separate “states”. Can you give a piece of code demonstrating some complex processing? Thank you.

  • Brendan Tompkins

    Jeremy, I think you’ve written a short book on this topic. It’s great!