Of Tailors and Tooling (rant)

Daniel asks a tailor to make him a suit. The tailor measures him and says “come back in three days.”

Daniel returns to try on the suit. “The left sleeve is too short” he complains. The tailor says “Raise your right shoulder and drop the left shoulder and you’ll look great.” Daniel does and, sure enough, the two sleeves meet properly at the wrist.

The left pant leg is too long” cries Daniel. “No problem” says the tailor. “Lift your left hip and walk on your toes.” Sure enough, both pant legs break beautifully just above the ankles.

Daniel pays the tailor and ambles out to the street wearing his new suit. Another man approaches him and exclaims “Wow, great suit! Who’s your tailor?”. Daniel beams and points to the tailor shop. “He must be a terrific tailor,” says the man, “to be able to fit a cripple like you!

I’m feeling like Daniel a lot lately. A number of us have been exploring implementation patterns for MVVM in complex, composite business applications. Just as we start getting somewhere promising … someone stops us short and says:

You can’t do that because it doesn’t work in Blend.

Let me be clear. I think Blend is grand and am learning to appreciate its power. I desperately want to facilitate the best possible UX. I know I can’t design the visuals worth a damn. I realize the people who can are not programmers and shouldn’t be asked to become programmers. I get it. I will do what it takes to make Blendable Views … including adjusting my posture.

But I’m not happy with show-stopper arguments like “It won’t work in Blend.” That may be the reality today but it need not be my future.

We should be honest about the consequences of saying “it won’t work in Blend”. Make no mistake, we’re twisting and contorting our architectures to satisfy the present state of the tooling.

Worse, we’re encouraging the tailor!

Sometimes I believe he thinks it’s a good thing for us to slouch and droop uncomfortably down the street. He actually thinks it’s a good thing to build View first, to inscribe code in the XAML, to block access to design-time APIs, to resort to Behaviors for simple programming tasks. He can’t believe I need to inject dependencies in the ViewModel … perhaps because that means he’d have to confront his own inadequacies.

I should get over it. Yet my hackles go up when I detect that smug, dismissive tone.

Hey, if you have to say “it won’t Blend” that’s an admission of failure. It means you’re not where you should be. I can deal with that. But stop sounding triumphant … as if what I want to do is stupid because it won’t Blend.

Yes, please make the tooling great for the designer. But the developer is the customer too … never forget that. The tooling should change to suit me … not the other way around.

Signed,

Frustrated-in-CA

Posted in Uncategorized | 7 Comments

Rob E’s Mini-MVVM Framework @ MIX10

Rob Eisenberg’s MIX 2010 talk, “Build Your Own MVVM Framework” was terrific. If you feel modestly comfortable with MVVM, run over and get the video and the code.

Rob may be best known for his Caliburn WPF/Silverlight Presentation Development Framework. That’s a hefty body of work and if the word “framework” sends an unpleasant shiver down your spine … relax yourself.

The “framework” demonstrated at MIX is roughly 500 lines (says Rob … I haven’t checked yet <grin/>). It’s based on Caliburn but stripped to essentials that Rob covered in an easy-to-follow, leisurely, one hour code-walk.

Highlights:

  • Simple MVVM
    • "VM first" in the sense that VM is in the driver’s seat.
    • No impediment to "View first" in the sense of view-design drives VM-design.
  • Simple naming conventions eliminate tedious code and XAML
  • Configuration at-the-ready when conventions fail
  • No code-behind … and didn’t miss it
  • No behaviors … and didn’t miss them (not that they’d be bad)
  • No XAML data binding; debuggable bindings created at runtime
  • No drag-and-drop binding … and didn’t miss it
  • No ICommand implementations and no event handlers
  • No files over 150 lines (as I remember)
  • Cool co-routines for programming a sequence of sync and async tasks; no call backs in the ViewModel
  • Screen Conductor pattern in play

All that in one hour.

The “co-routine” trick alone is worth your time. You almost get F# “bang” syntax in C#.

It could get more complicated in your app … and you’d have Caliburn. But it might not  … and you’d be living large with dead-simple, DRY code.

One of the best sessions ever.

If only we could teach Rob to emote. The guy is passionate on the subject but you might miss it behind that mono-tone voice of his. A Jim Carrey he is not. You want entertainment? Look elsewhere. You want substance … tune in.

He got a big ovation, by-the-by, so it ain’t just me who liked it.

Posted in MVVM | 2 Comments

MVVM, Josh Smith’s Way

I’ve long admired Josh Smith’s work. He’s one of the best explainers on the web and he – together with Karl Shifflett and Andrew Smith – gave us Mole, the superb WPF Visual Studio debugger visualizer.

I heard recently that he’d published an e-book on Model-View-ViewModel (MVVM). I met him for the first time at the Microsoft MVP Summit last week and he graciously handed me a printed copy. I devoured it on the plane home and spent the next day playing with the code and preparing this review.

It’s called “Advanced MVVM” and you can buy a printed copy for $20 or get it for $15 on the Kindle. The companion code is freely available at AdvancedMvvm.com .

$15 bucks for a 52 page “book”? It’s more of an extended essay to be honest … an essay with code. After spending some pleasurable hours with both book and code I thought “where do you get that kind of entertainment / self-reflection for $15?” I have a surfeit of 600 page sleepers lounging on my bookshelf at home; paid more then $50 for each and hardly cracked them. Should we pay by the pound? So I’m over it. I don’t mind paying for the hours Josh poured in and the fun I got out. Set your expectations appropriately and you’ll feel fine.

—- 19 March 2010 Note —

Ok, it’s been a month or so since I wrote this. Life happens while you’re making plans. I intended to be among the first to comment on it. I’m late to that party (although I have deliberately NOT looked at what others may have said) so I’m not sure if it’s still timely. I also shared it with Josh last week to see if I had missed something and get his feedback, particularly in light of my critical remarks.

He encouraged me to publish it even at this late date. I hope he’ll repost here some of his responses to the points I raised.

———————————-

MVVM has spooked a lot of developers. There’s more than a whiff of astronaut architecture about it. There have to be at least 20 MVVM frameworks and no end of contentious arguments to confound and distress you. No wonder so many are put off.

MVVM in a Nutshell

In fact MVVM is fundamentally a simple idea. It starts with the realization that your application is an intractable mess in part because you dumped all of your UI logic into the code-behind … with the help of Microsoft tools. You discover the wisdom of pulling much of that logic out into a companion class (and some helpers) leaving the view class to concentrate on looking pretty and capturing user gestures. The view and its companion must talk; you can structure their conversation according to a variety of familiar patterns. Model-View-ViewModel is one such pattern.

The predominance of automated binding is the hallmark of MVVM. You bind a View’s textbox to a string-providing property of the ViewModel so that a user’s changes in the textbox flow to the property and so that programmatic changes to the ViewModel property flow back to the textbox. You bind View events (e.g., button click) to event handlers in the ViewModel enabling user gestures to be conveyed to the ViewModel.

You could write your own bindings by hand, pushing and pulling data and events with custom code. That’s a lot of work. The XAML-based client technologies (WPF and Silverlight) provide a binding framework that requires little to no custom coding. In most cases you can “connect the dots” declaratively and it just works.

Now the View concentrates on appearance and the ViewModel feeds the view. This separation is both clarifying and liberating. You can start looking at that ViewModel to figure out what it should do and how it should do it without also worrying about the visuals. The subsequent examination of ViewModel’s more limited responsibilities sets you on a more sustainable course. At least this has been my experience … and that of the hundreds (thousands?) of other developers who’ve adopted this pattern.

Now you’ll note that I said it “sets you on course”; I did not say it delivers you to the promised land. There are details to work out. If the View looks to the ViewModel for data, where does the ViewModel get that data? Are we talking about data values alone or the business rules that surround that data, rules about data validity, integrity, security, and persistence?

Many of us draw a circle around these concerns and call that circle “the Model”, the third element in the MVVM triad. Our guiding intuition is this: “the persistent data are definitely in the model and if the rules about data are true for this and every possible UI, the rules belong in the model as well.”

If the last name is required, it is required everywhere; that’s a model rule. If gold customers can select from several thank-you gifts, that sounds like UI logic to me … and belongs in the ViewModel. The specifics have to be worked out.

Back To Josh

At this point the discussion risks slipping into theory and theater. We could run to the white board, scribble madly, and count angels on pins without writing a line of code. I love doing that.

Josh has taken another direction which is likely to be both more popular and more effective. He briefly presents his take on MVVM in clear, accessible prose … and then makes it tangible with an extended exploration of a meaty sample application. I’ve read plenty of pattern papers; I don’t remember any that were so thorough … and entertaining … in their examples.

For style and substance this is a remarkable achievement. I truly hope that Josh’s book is widely read because I think it has a better chance of helping WPF and Silverlight developers feel comfortable about MVVM than anything else I’ve seen.

I’m a little worried that some will fear the word “Advanced” in the title. The term “MVVM” is forbidding enough and many folks are still looking for the introduction. I think this book is the introduction they really need.

In what sense is it “advanced”? It’s far from the last word on the subject. It won’t settle any arguments (least of all mine). But it does rise above the introductory level in two important respects.

First, it considers the implications of multiple, cooperating MVVM instances. Most MVVM articles present a single MVVM-triad: a single View and its companion ViewModel and Model.

No application needs a single MVVM triad. If you have a one-screen application, don’t use MVVM; it’s overkill. MVVM is for multi-screen applications consisting of multiple MVVM triads which spring to life somehow and somehow interoperate.

Second, as I noted earlier, Josh doesn’t just talk about the pattern. Most of the pages describe the accompanying game, BubbleBurst, which is implemented in MVVM style. Instead of paeans to principles and their wondrous benefits, you see MVVM in action, warts and all.

BubbleBurst is “advanced” enough to both introduce MVVM and reveal important implementation challenges of multi-MVVM applications. Yet it’s simple enough to be easily understood in the pages of a book or in a few hours spent trolling the code. It’s also fun to play.

Proceed with Caution

I’m about to begin my critical remarks. Before I do, I want to reemphasize my enthusiasm for what Josh has accomplished. This book is a wonderful place to begin your MVVM journey and I found it to be an enjoyable and insightful read. So, hell-yes, I’m recommending it.

On the other hand, it would be a shame if developers stopped their education here. Important elements of the story are missing and many recommendations are seriously misguided in my view. Readers should take Josh seriously but, once they are comfortable with the pattern, they should become aware of starkly contrasting perspectives as well.

Critical Omissions

Four vital topics are neither covered nor illustrated in the code:

  • Testing
  • Model (the first ‘M’ in MVVM)
  • Dependency Injection
  • Event Aggregation

Testing

Josh asks “What is the point of having ViewModels?” First among his reasons: “the ability to easily write unit and integration tests for the functionality of the user interface without having to get into the messy world of writing tests for live UIs.

That’s the last we hear of testing. There is not a single test in the code base. If testing is as important as he says, I’d expect a thorough treatment starting with building a test regimen and showing, by example, how to write good tests. Instead, we get lip service.

I don’t think testability is the only value of MVVM. I couldn’t recommend it for this reason alone. MVVM is a significant architectural investment that introduces complexity. I wouldn’t incur that complexity cost merely to make my UI testable. I’d look for a less onerous route. Fortunately, I think it has other benefits such as clean separation of concerns, improved readability, and easier debugging (try break-pointing XAML!).

But testability is both a motivation for and a by-product of MVVM style and it should have been covered thoroughly in an “advanced” treatise on MVVM.

Moreover, the design would have benefitted greatly from attempts to test it. Many lines of view code-behind are both untestable and harder to follow than they should be. I see early signs of the spaghetti code that afflicts more complex and mature applications … a drum I’ll beat furiously later in this review.

At almost 300 lines, the BubbleMatrixViewModel begs to be tested both for quality and to reveal the expectations latent in its 20+ public and internal members.

The Missing Model

The pattern is called Model-View-ViewModel. Josh’s Model is nowhere to be found. Model and ViewModel are combined and it’s not clear to me how one would disambiguate them.

The absence of Model isn’t blatantly obvious in a simple game like BubbleBurst. The game doesn’t to retrieve or save objects to a persistent store. We aren’t expecting much in the way of business model logic either; there’s nothing of interest to validate or secure. So the lack of a model is not a deep fault of this particular application. Indeed, it’s a convenient way to concentrate our attention on the central issues for most students of MVVM:

  • What code belongs in View and what code in ViewModel?
  • How do View and ViewModel interact?
  • How do you instantiate Views and ViewModels?

Nonetheless, we can’t pretend to provide a comprehensive guide to MVVP without talking about the Model and how it interacts with ViewModel and (to a lesser extent) View. A business application will demand a clear delineation of responsibilities and equally clear communication paths.

I’m not letting BubbleBurst off the hook either. I felt on several occasions that some ViewModels were heavier and more complicated than they should be because an inchoate game model was not independently defined.

Dependency Injection

I appreciate that Dependency Injection frightens many developers. You can discover MVVM without learning about Dependency Injection. Josh can kind of get away without it as long as he doesn’t test his ViewModels and doesn’t have to think about the services required to manage a persistent model.

But I feel you can’t call this “Advanced MVVM” … or even “Intermediate MVVM” … without introducing DI at some point. In Josh’s application, every View and every ViewModel class is known to and instantiated by some other View or ViewModel class. That won’t fly in real-world applications which have Views and ViewModels that are ignorant of each other.

The constructor of the BubbleMatrixViewModel instantiates three concrete bubble components: BubblesTaskManager, BubbleFactory, and BubbleGroup (twice) before making heavy use of them.  That’s a lot of dependencies that would make this ViewModel brittle and especially difficult to test.

Taking hard dependencies means Josh can freely assume that ViewModels will always have parameterless constructors and can always be instantiated in XAML, as he often does here. Someone new to MVVM might think this is the norm. It is not.

Josh himself alludes to DI as one of the avenues opened by the MVVM pattern: “[MVVM] means that you can use frameworks like MEF to dynamically compose your ViewModels, to easily support plug-in architectures …”. That’s the last we hear of MEF or dynamic VM composition.

Again, I think we can ignore DI in an introduction to MVVM; we cannot ignore it in an advanced lesson on MVVM.

Event Aggregation: communicating with the unknown

All of Josh’s MVVM triads are statically determined. Their relationships to each other are fixed and well known.

I was surprised to see a ViewModel for one view hold a reference to a ViewModel of a subordinate view. That’s not how I do it; my general rule is that MVVM triads do not hold references to each other. I concede that the rule makes it difficult to organize cross-triad communication. Josh’s approach is simple and elegant … when available.

In real-world business applications, the MVVM triads often can’t know about each other. They are often defined in separate modules without mutual references. Views appear and disappear dynamically. Direct communication is frequently impossible.

That’s why so many so-called MVVM frameworks include some kind of messaging or Event Aggregation infrastructure. You don’t need them to understand MVVM triads in isolation. But you never see an application with a single MVVM triad and you rarely find an MVVM application with statically determined, session-permanent views. No “advanced” treatment of MVVM can neglect Event Aggregation.

View First or ViewModel First?

Here’s an incendiary topic Josh leaves untouched.

I see two ways to ask this question:

  • Do I design the View first or the ViewModel first?
  • Do I instantiate the View first or the ViewModel first (or does something else instantiate and wed them)?

The answer to both questions need not be the same. For example, you could decide to design the ViewModel first and let the View instantiate that VM at runtime. This is plausibly the approach advocated in BubbleBurst although Josh never talks about it.

Again, it’s important that readers new to MVVM learn that Josh’s way is not the only way.

View and ViewModel Design

In my experience there is a “dialog” between View and ViewModel design. The VM exists to serve a view even as it strives for independence from any particular concrete view. A VM is useless if  there is no view that will work with it; clearly the VM developer must heed the imprecations of the View developer.

On the other hand, in business applications the application’s imperatives – what the view must do to satisfy business requirements – are the province of the programmer and are best articulated through the capabilities of the ViewModel.

Therein lies the necessary tension between View and ViewModel design. As a developer my allegiance is with the ViewModel (“the application should do something worthwhile”) but it would be silly to defend that allegiance at the expense of the View (“a good UX is essential to making an application easy to learn and to use”).

I’d have liked to see this tension at least acknowledged and perhaps explored.

Who begets Whom?

Runtime construction is a question apart from the matter of who drives the design. WPF and Silverlight tooling push you toward “View First” construction in which the View instantiates the ViewModel. You’ll often see the View’s DataContext set by a ViewModel instantiated in the XAML as shown here:

  <UserControl.DataContext>
     <viewModel:BubbleBurstViewModel />
  </UserControl.DataContext>

Contrast this with the ViewModel first, code-based approach (not seen in BubbleBurst) in which the ViewModel is assigned to the View’s DataContext as follows:

 view.DataContext = viewModel;

The View First approach assumes that the ViewModel can be created via a default, parameterless constructor. That’s fine for BubbleBurst but wholly unrealistic in business applications whose ViewModels have dependencies (e.g., on the domain model).

Neither WPF nor Silverlight XAML support the dependency injection mechanisms that many of us prefer. I wish Josh had talked about this and perhaps discussed the interesting attempts to use MEF dependency injection (via properties rather than constructor arguments)

I’m not trying to settle these questions. I am saying these questions could have been called out in an “advanced” book on MVVM patterns.

What Belongs In Code-Behind?

Do we allow or prohibit code-behind? That’s a fist-fight topic. Josh looks for a Goldilocks solution, suggesting the amount of code-behind is just right if confined to “logic scoped to the view”.

Such guidance is far too loose in my opinion. It’s not effective guidance at all.

We choose presentation separation patterns in part because we want to minimize testing of the view. We should test any custom logic we write – no matter how it is scoped. The poverty of our testing tools means that, in practice, we will not test the code in the view. Therefore, any code in the code-behind is suspect.

I am open to some code in the code-behind; the “InitializeComponent” method is inescapable. I’ll accept a minimum of “switch board” code in the code behind; direct wiring to a ViewModel member is ok in small doses.

I draw the line at decision logic. I smell a rat when I see a conditional statement of any kind. That’s where bugs breed. Conditional logic is code we should be testing.

I much prefer this rule: “No conditional logic in the code-behind”.

That’s unambiguous. We don’t have to wonder what “scope of the view” means. If there’s an “if” or a “switch” statement, something is wrong. You can detect a violation with automation or visual inspection. It’s a rule that’s easy to follow and pretty easy to abide by … when you know how.

What happens when you don’t follow this rule? You’re lured into the kind of dodgy code that … well we see in the innocent seeming BubbleMatrixView.xaml.cs.

In fact, far from being “best practices”, I’d say that the View code in BubbleBurst represents some of the worst practices.

Look at the HandleMatrixDimensionsAvailable method. This event handler is wired to a UI element in the BubbleBurstView. Unfortunately, the UI element happens to be in a different view, the BubbleMatrixView! One view’s code-behind is wired to members of another view; that’s the road to perdition. That would never pass my review.

I wanted to clean it up immediately. I tried to find the intention behind this practice. Usually I look to the name of a method to discover its purpose. Unfortunately the handler is named for the moment when it is called (“Matrix dimensions available”) rather than for what it does. That’s conventional naming for event handlers but not terribly informative. Unless a handler is brain-dead-simple, I have it delegate immediately to methods with meaningful names. The handler tells me when something happens; the inner method tells me what will be done.

Had Josh adopted my suggestion, he’d have realized that his handler has multiple responsibilities:

  • wires the outer window’s keydown event
  • picks up the dimensions of the related view’s grid
  • starts the game

That’s too much work for code-behind in my book.

When we strive to apply the “no conditional logic in the code-behind” rule, we discover other design problems.

It appears that Undo logic is distributed between two ViewModels. One of them, the BubbleBurstViewModel, determines if undo is possible while the second, BubbleMatrixViewModel performs the undo. Probe further and we find that even the BubbleBurstViewModel test for undo-ability is delegated back to the BubbleMatrixViewModel. The ping-ponging among Views and ViewModels is confusing; it doesn’t smell right.

All the signs suggest the real action is in BubbleMatrixView and its ViewModel.

BubbleMatrixView.xaml is short and sweet.The code-behind in BubbleMatrixView.xaml.cs is another story. Five Region tags sound the alarm. You shouldn’t need region tags in code-behind. Here they barely disguise the complexity of 145 lines of code-behind. That can’t be right.

MicroControllers: BubblesTaskPresenter Example

I was able to refactor the 53 lines dedicated to animating bubble tasks. Most of them went to a BubblesTaskPresenter class, a component Jeremy Miller calls the “MicroController”.

Every MVVM developer should become familiar with the “MicroController” approach.

A “MicroController” performs a narrow UI task on behalf of a view. We usually write one to encapsulate UI logic that is reused across multiple views. That’s not the case here; the application is too small.

We also write MicroControllers to encapsulate UI-specific functionality in a UI-agnostic wrapper. They make it easy for non-UI components, such as ViewModels, to invoke the UI-specific behavior we find in Views. That’s what we need here.

I noticed that the ViewModel holds a TaskManager which raises a PendingTasksAvailable event when there are bubble display tasks. This sets off a sequence of calls between View and ViewModel which collectively “process tasks” queued up by the ViewModel.

Josh’s original code forwarded the event to the View’s code-behind. That code-behind then extracted the VM’s TaskManager and called into it. 53 lines of code-behind are dedicated to this entire process.

After my revision, the view merely provides the ViewModel with a configured MicroController, here called a “BubblesTaskPresenter”:

 _bubbleMatrix.BubblesTaskPresenter = new BubblesTaskPresenter(_bubbleCanvas);

This is what switchboard code should look like. I’d like to get rid of the instantiation but at least there is a bare minimum of logic and no conditionals.

The ViewModel receives the concrete presenter in the guise of a UI-agnostic interface, IBubblesTaskPresenter and wires itself to the presenter’s events.

    public IBubblesTaskPresenter BubblesTaskPresenter {
      get { return _bubblesTaskPresenter;}
      set {
        _bubblesTaskPresenter = value;
        _bubblesTaskPresenter.Completed += delegate { ProcessTasks(); };
        TaskManager.PendingTasksAvailable += delegate { ProcessTasks(); };
      }
    }
    private void ProcessTasks() {
      var task = TaskManager.GetPendingTask();
      BubblesTaskPresenter.PresentTask(task);
    }

IBubblesTaskPresenter uses simple .NET types and looks like this:

  /// <summary> 
/// Interface for a presenter of <see cref="BubblesTask"/>
/// </summary>  
public interface IBubblesTaskPresenter {
     void PresentTask(BubblesTask task);
     event EventHandler Completed;
}

Where did the 53 lines of code-behind go? Into the BubblesTaskPresenter.

What has been gained? Did I just hide the pea under another untestable cup called a “presenter”? Is this merely an academic exercise?

I don’t think so. True, the presenter is dependent upon WPF and upon BubbleCanvas in particular. But it could be tested with a faked canvas and a faked factory. Testing aside, it’s small and focused; it’s easy to see what it does and how it works. It won’t get lost amidst the other motions of the BubbleMatrixView. We might someday use it in another view that presented BubblesTasks.

The BubbleMatrixViewModel has grown a few lines but remains readable and testable; its imported IBubblesTaskPresenter is easy to fake.

The ViewModel no longer exposes the TaskManager. That’s a good thing because the TaskManager is pretty complex piece of machinery with a rich API. We don’t want the View or BubblesTaskPresenter to know about it.

And the View is 53 lines lighter, reducing the anxiety we might justifiably feel if we handed it over to a non-programming designer for styling.

Homework Assignment: if you’re playing along and are looking toward your own application design, you might want to linger over the BubblesTaskPresenter. It is specific to bubbles right now … which is appropriate in the absence of forces that would drive us to generalization.

But you can encapsulate storyboard animations in much this way to both determine state changes within the ViewModel and externalize the animations in “View-space” where they belong. Josh is spot-on when he insists on this separation. The MicroController “presenter” approach is one way to achieve that separation without polluting the code-behind.

Aside: my first presenter was more abstract and general purpose. My generalization was premature. Generalization made the code more complex than it needed to be in this application. I un-factored it to the current version that knows about BubbleCanvas and BubblesTaskStoryboardFactory.

Views Shouldn’t Talk To Views

After clearing out the 53 lines, I was able to focus on what’s left.

I was deeply troubled by the properties of BubbleMatrixView that are exposed to and consumed by the BubbleBurstView code-behind. That can’t be right. Views shouldn’t need custom properties.

If you have to expose a custom view member, you should do so through a view interface. We don’t want any code – View or ViewModel – depending upon a concrete view class. That’s asking for trouble and flies in the face of the testability which justifies MVVM.

It’s also completely unnecessary in this application. As noted earlier the event loop from inner BubbleMatrixView to outer BubbleBurstView leads back around to BubbleMatrixView’s ViewModel. We can cut all that nonsense out and simply update the BubbleMatrixViewModel directly in the code-behind … without any conditional logic.

I refactored as follows:

  • Removed 30 lines from BubbleBurstView code-behind
  • Added “StartTheGame” to BubbleMatrixViewModel; it combines the functions of setting the dimensions (now private) and starting a new game.
  • Removed 61 lines from BubbleMatrixView code-behind which now calls StartTheGame when the canvas is loaded. Region tags are gone.

The BubbleMatrixView code-behind is now a trim 30 lines with no conditionals, down from 145 (80% reduction). Of the 30, exactly 5 of them do work.

My cleanup involved eliminating several null checks. They never did anything useful. First, the variables could not be null in practice. Second, even if they were (e.g., someone broke the xaml), the application would not have functioned anyway. I don’t think a blank screen is superior to an exception. The null checks were about as helpful as empty catch blocks.

Tidy-up BubbleBurstView Code-Behind

BubbleBurstView’s code-behind had one remaining “if” and some other code that I felt didn’t belong there.

Key monitoring logic contained an “if” statement. At first it seemed like key monitoring was a candidate for another MicroController. But there is only one key to handle, the key for Undo. That wasn’t worth the overhead of another MicroController component. Instead I decided to enrich the BubbleBurstViewModel with an Undo method whose signature is:

  public bool TryUndo(bool shouldTry) // returns True if undid

The code-behind calculates whether the key presses amount to an undo request. The call is:

  e.Handled |= _bubbleBurst.TryUndo(isUndoKey);

I don’t like the isUndoKey calculation but I’ll leave it for another day.

My final bug-a-boo is the LoadBubbleViewResources method which instantiates a ResourceDictionary and plugs it into the application-level resources.

I expected this to be loaded by the App.xaml itself but I suspect Josh wants to simulate the notion that independent assemblies have their own resources. While the “Bubble.View” assembly is not independent – the App.xaml has access to it through its host assembly’s references –, I’ll play along.

In any case, the view’s code-behind shouldn’t know the details of ResourceDictionary construction and App.Resources update. Time for a MicroController: “BubbleViewResourceLoader” which we can invoke from within the code-behind’s constructor for now. It still stinks but it stinks less.

The code-behind now stands at 41 lines, down from the original 86; only 9 of them do work.

Picky, Picky

I’m a restless complainer. I’ve got a few more bones to pick having nothing to do with MVVM.

Page numbers! You may have noticed that my citations lacked page numbers. That’s because there aren’t any in the printed document I’m reading.

The abundance of Region tags annoys me. Hey, I use them too, especially in pedagogical code where I want to unveil new ideas didactically in the course of a presentation.

I appreciate that they seem to organize the code into nice buckets: “constructors”, “methods”, “fields”. But lately I’ve come to believe that they’re more of a code smell.

If the class is short – as it should be – they interfere with my ability to read and grasp the class at a glance. If the class is long, they suggest that my class implements too many distinct concerns and I’m struggling – vainly – to keep them organized. These concerns would be better delegated to supporting classes. I suspect that automated testing would make this defect more obvious.

I’m not thrilled with the data triggers. Data triggers are not available to Silverlight programmers probably for good reason. The Visual State Manager is the preferred choice for both WPF and Silverlight.

A particularly egregious data trigger can be found in BubbleBurstView.xaml where the GameOverView is collapsed when the BubbleBurstViewModel’s GameOverViewModel is null. Could there be a more obscure way to signal that a modal dialog should be hidden? I suspect a bound IsGameOver property would be both simpler and more obvious.

Where’s The Code?

Josh’s original source is at AdvancedMvvm.com . I’ve temporarily posted my refactored version on my site. I’m not promising it will stay there- this is Josh’s code and I’ll do whatever he wants me to do with it (including burn it) – but it’s there now and I’ll let you know if I move it.

Wrap Up

I have high hopes for the conversation Josh has started with this book.

I see it as one place to begin your study of MVVM rather than as the definitive work on the subject. Some of the practices I find dubious and there are serious omissions.

But I gave it this much attention because it deserves it. It’s a fine piece of writing, a carefully considered example, and a push in the right direction. Josh speaks to a broad audience with an authentic voice they understand and respect. He has my respect as well.

It’s well worth the $15 bucks on the Kindle.

Enjoy!

p.s.: Cross-posted to my other blog, “Never In Doubt

Posted in MVVM | 8 Comments

An IoC-Agnostic Prism Bootstrapper

Prism from Microsoft Patterns & Practices leans on an Inversion of Control (IoC) container. While nominally indifferent to your choice of container, you have to work a bit to extricate yourself from its default choice which is Microsoft Unity. More so with some containers than others.

The sweat and tears flow in the “Bootstrapper” class with which you launch your application. Most Prism samples feature a Bootstrapper that inherits from “UnityBootstrapper”. “UnityBootstrapper” busies itself with registering and configuring a dozen or so Prism components in a manner characteristic of Unity and it unapologetically takes a hard dependence on Unity itself. You are welcome to write your own Bootstrapper base class from scratch; of course this entails reading and understanding what “UnityBootstrapper” does so you can reassure yourself that your replacement achieves the same effects. Who has time for that?

Almost a year ago I found myself writing a single application with three different client technologies, each dependent upon its own container. The three diverged in minor details – each was a different incarnation of a Container + ObjectBuilder – but the differences were sufficiently great that I felt compelled to unleash the Prism base bootstrapper class from its Unity chains.

Preoccupied with more important business, I took the most expeditious route. I salvaged as much of Prism’s UnityBootstrapper as I could while replacing its direct dependency on Unity library references.

Prism initialization is not something I want to own. When P&P updates its UnityBootstrapper, I want a quick, no-thought pathway to update my IoC-agnostic version.

The result was Cal.Bootstrapper (“CAL” is short for “Composite Application Library”, Prism’s official name) and some supporting types. Cal.Bootstrapper looks like a cleaned-up UnityBootstrapper. It goes through the same motions of registering types and configuring instances albeit with reference to a denuded IoC, shorn of all but the most minimal functionality. This, dear reader, will be my gift to you.

Recently, a few folks have wondered about replacing Unity with a completely different IoC container. The one I hear most often is StructureMap. Its author, Jeremy Miller, has several times entertained the notion of replacing “UnityBootstrapper” with something that reflects glory on StructureMap. Apparently he has better things to do. I guess I’ll tackle it.

The Goods

I’ve bundled everything described in this post into a 2 meg zip, PrismRI-Ioc.zip, downloadable from my company website. Do with it as you will.

Please note: I have no intention of maintaining this; don’t even ask.

No, This is Not the Right Way

My knowledge of StructureMap is deeply impoverished but, from the little I do know, I’m certain that the “proper” course is to abandon “UnityBootstrapper” altogether. But there’s a reason Jeremy hasn’t tackled this and no one seems to have done so for other IoC products either.

Nicholas Blumhardt, author of Autofac, took a crack at integrating Prism with his IoC back in August, 2009. He wanted to do it “the right way,” completely rethinking how a Prism app is bootstrapped and how application modules are written. He describes it here as a “work-in-progress”. I guess it took a little more work than he thought it would and he must have found something better to do because it doesn’t look like he finished.

I hoped to avoid this “road to good intentions” by doing it the “the easy way” which may be the “wrong way” but it works … which beats something that doesn’t.

I decided to change as little of the Unity-oriented Prism app approach as I could. I want to get something done. I want you to be able to convert your running Prism app with minimal effort.

Accordingly, my “Cal.Bootstrapper” mimics the “UnityBootstrapper” and it wallows in the style and ceremony that other IoC products despise.

Is it all that bad? Why am I changing my IoC container anyway? I ought to have a clear idea about what I want from an alternative to Unity. I’m wasting my time if I’m only replacing the UnityBootstrapper with something “better”. Frankly, I don’t care how Prism configures its minimal requirements. If I want StructureMap (or AutoFaq, Castle Windsor, Ninject, etc), it is because I prefer that IoC for registering and configuring my own application components. I may replace the Prism configuration eventually but right now that is neither my motivation nor my first step.

Therefore, although my Cal.Bootstrapper is ugly as sin, it will serve me for the nonce as I hope it serves you and I shall proceed to describe it without further apology. I will let it configure Prism the ugly way using my IoC container in place of Unity after which I am free in my own code to drive my IoC container as it was meant to be driven.

Battle Plan

A Prism application has a Bootstrapper class to configure the container, create and configure the main UI view called the “shell”, acquire application modules, and launch the application.

You are expected to write a custom Bootstrapper that inherits from a base Bootstrapper class provided by Prism (the aforementioned UnityBootstrapper). This base class handles the above inventory of start-up tasks. Your derived Bootstrapper is supposed to extend the base class by overriding certain abstract and virtual methods.

In other words, the bootstrapper is launch karaoke. You add your voice at predefined moments. It’s great if the music suits you. If you’re singing off key, you’re should stop faking it and write your own song.

Tempted as I was, I chose not to quarrel with this approach. In fact, I took a deep breath and then embraced it … for the reasons discussed above.

I decided to replace the UnityBoostrapper with an alternative base class (Cal.Bootstrapper) that does not know about Unity.

Your derived Bootstrapper will provide an IoC container to this base class, wrapped in a vendor-neutral “ContainerAdapter, and delivered to the base class by overriding its abstract “CreateContainerAdapter” method.

I have a few additional goals:

  • “Improve” the UnityBootstrapper so I can figure out what it does.
  • Make it easy to update my base class when (if) Microsoft updates the UnityBootstrapper.
  • Minimize the effort to get my existing app bootstrapper deriving fro the IoC-agnostic base class.
  • Minimize the changes necessary to convert my existing Unity-based Prism app.
  • “Prove it” with an app Prism-aficionados know: the Prism Reference Implementation.

The original UnityBootstrapper is code only a mother could love. Long methods; much repetition; mysterious names. I can’t replace it until I understand what it does. My first step is to refactor it for readability. This is somewhat a matter of taste but I hope you’ll agree that the my revision, called “RefinedUnityBootstrapper”, is an improvement.

I mustn’t get carried away if I am to satisfy my second subsidiary goal. Too many improvements would hinder re-synchronization with Microsoft’s changes.

I want to prove that my approach works on an “application” that anyone can examine and that would be familiar to Prism developers. The Prism RI is the obvious candidate; that’s what I tackled.

I haven’t looked at the RI in a long time. The version on my disk dates from February 2009. That’s pre-Silverlight 3 and, although I had patched it for SL 3, it’s still old and funky. The UI doesn’t work the way it should: stock positions don’t change when you buy and sell, the “Watch List” feature is broken, the Silverlight version throws a recoverable exception when you sell more stock than you own.

But I didn’t have time to freshen it up, it was good enough for my purposes, and it’s all I’m going to give you.

Swappable Versions

This is a tutorial. I want you to be able to switch among different container implementations without changing the body of the application. I don’t have the time or the interest to do anything fancy.  In the “real” world, I’d make the change and discard the original.

The version of the RI you run depends entirely upon the executing version of Prism RI Bootstrapper class. The class is divided into two partial class files. One of them is constant. The other holds just the code that varies from container to container. The file with variations is called StockTraderRIBootstrapper.Ioc.Desktop or StockTraderRIBootstrapper.Ioc.Silverlight.

The variations are governed by compiler directives at the top. You uncomment ONE of them, recompile, and let ‘er rip. The example below shows the bootstrapper readied for StructureMap.

//***************************************************************************
// *** PICK YOUR BOOTSTRAPPER AND IOC CONTAINER WITH _ONE_ OF THESE DEFINES

//#define ORIGINAL_UNITYBOOTSTRAPPER
//#define REFINED_UNITYBOOTSTRAPPER
//#define UNITY_CONTAINER_ADAPTER
#define STRUCTUREMAP_CONTAINER_ADAPTER
//#define AUTOFAC_CONTAINER_ADAPTER

//***************************************************************************

Each variation takes only a few lines. I set the title text so you can see which version is running on screen (the original three letter “CFI” company name changes to one of “OUB”, “RUB”, “UCA”, “SMA”, or “ACA” to match your selection). For the Ioc-agnostic variations, there is an override of the method that creates the selected Ioc ContainerAdapter. The two versions pinned to the UnityBootstrapper (remember that I “refined” the UnityBootstrapper first simply to understand it better) have a shim method instead.

Incredibly stupid, I know. I’d never ship anything like this. I live with it because it’s a throw away demo and doesn’t merit the effort or complexity of proper decoupling. Or at least it doesn’t merit that attention yet.

The rest of the Prism RI stays constant. It took some work to keep it that way. Not a lot, fortunately; the Patterns and Practices people did a pretty good job of keeping the RI Ioc-neutral.

I won’t bore you with the details of my journey to this blissful place. They are chronicled in “PrismRIChanges.txt”, located in the PrismRI folder next to the Visual Studio Solution file, “StockTraderRI-IoC.sln”. The gist of it is

  • Add the Ioc assemblies in a common directory structure
  • Add the PrismBootstrapper solution with its Ioc-agnostic Cal.Bootstrapper and the Ioc-specific ContainerAdapters.
  • Revise the start-up project, StockTraderRI, to access the above
  • Replace references to “IUnityContainer” with “IContainerAdapter”
  • Remove module references to Unity.

You’ll do pretty much the same if you convert your existing Prism application to another Ioc container.

ContainerAdapters

The fun is in the ContainerAdapters which implement the following interface:

namespace Cal.Bootstrapper {
  public interface IContainerAdapter {

    IContainerAdapter RegisterInstance<T>(T instance);

    IContainerAdapter RegisterType<TFrom, TTo>(
        ContainerRegistrationScope scope) where TTo : TFrom;

    IContainerAdapter RegisterType(
        Type fromType, Type toType, ContainerRegistrationScope scope);

    IContainerAdapter RegisterTypeIfMissing<TFrom, TTo>(
        ContainerRegistrationScope scope) where TTo : TFrom;

    IContainerAdapter RegisterTypeIfMissing(
        Type fromType, Type toType, ContainerRegistrationScope scope);

    T Resolve<T>() where T : class;

    object Resolve(Type type);

    T TryResolve<T>() where T : class ;

    object TryResolve(Type type);
  }

  public enum ContainerRegistrationScope {
    Singleton,
    Instance,
  }
}

Not so bad if you know your container. Clearly IContainerAdapter must be so dumb that any IoC Container vendor can support it. It needs to be just smart enough for the base Bootstrapper class to configure Prism. Fortunately, this challenge is easily met.

The code tends to be boilerplate. Autofac took a little more work (see below) but still weighs in at only 180 lines.

You also have to write an adaptor that implements Microsoft.Practices.ServiceLocation.IServiceLocator; virtually everyone has done this already.

IoC Containers Demo’d

I’ve tried this approach with three IoC Containers: Unity (Unity v.1.2.0.0, ObjectBuilder2 v.2.2.2.0), StructureMap (v.2.5.4.0), and Autofac (Desktop: v.1.4.5.676, Silverlight: 1.4.4.572).

You should know that I am not an expert in any of these containers. In fact, I just winged it, especially with StructureMap and Autofaq about which I know squat. I figured I could download them, skim whatever documentation they offered, and get something to work adequately for Shmoes like me.

It’s not quite that easy and I have low confidence in my use of these containers. Their authors are invited to lend a hand improving matters … after they’re done laughing.

I wanted to show at least one non-Unity container for both desktop and Silverlight applications. StructureMap doesn’t have a Silverlight version yet (come on, Jeremy). I tried Autofac because it does have a Silverlight version.

I’m glad I did. The StructureMap implementation was a breeze. Autofac was much harder. I’m not trashing Autofac. It just happened to be harder for me, partly due to my ignorance and mostly because of the position Autofac takes on resolving unregistered types.

Major Container “Gotcha”

Container differences matter! One pervasive Prism practice in particular relies on a Unity default behavior that other containers do not observe. It’s serious enough to influence your choice of containers or make your conversion substantially more difficult.

Prism instantiates a lot of its own components with unregistered public concrete classes. For example, somewhere in the bowels of RegionManager initialization, it resolves “DelayedRegionCreationBehavior”. This class is never registered with the container.

Unity is ok with this. When asked to resolve an unregistered public concrete type, it treats the type as if it had been registered and scoped as an instance (i.e., you get a fresh instance each time). Both TryResolve and Resolve behave this same way.

Prism components count on this default Unity container behavior. What if you change containers?

StructureMap has the same default behavior when resolving an unregistered public concrete type. However, it’s TryResolve equivalent, “TryGetInstance”, return null. As I write, I have not detected a consequence of this difference; but I know it’s waiting in the grass somewhere.

You could argue all day about whether a container should return null or return an instance the way Unity does. You could argue whether it should default to Singleton or Instance scope.

Autofac punts. If you attempt to Resolve an unregistered type, it throws an Autofac.ComponentNotRegisteredException with a clear message. “TryResolve” returns null, which is the sensible thing to do.

Aside: the three ContainerAdapter files in my sample implement a “ContainerPlay” class that reveals these differences.

I can’t quarrel with Autofac’s choice but I sure paid the price for purity. I had to hunt down all resolutions of concrete types and manually register them during AutofacContainerAdapter initialization. Unfortunately even that is insufficient. Many class constructors take parameters defined by concrete types. The container will attempt to resolve these and will throw at runtime. There aren’t integration tests to detect these automatically so I have to wander through the app under the debugger. I still haven’t got it to work.

It was easier to get the Prism RI working with StructureMap. I have assumed that the only critical difference is with explicit “TryResolve” calls. I haven’t encountered any optional constructor parameters so I expect StructureMap and Unity to resolve these in the same way.

I searched the Prism and RI source code for “TryResolve” calls involving concrete type. There weren’t many of them. I only found one of potential consequence. The base bootstrapper calls “TryResolve<RegionAdapterMappings>”. Fortunately, it also registers RegionAdapterMappings explicitly so resolution is always successful. Perhaps I was luck. Remember to be careful how you use TryResolve in your application.

The net of it is that containers differ. Prism should not have relied on a Unity-specific type resolution feature. If you have done so in your Unity-based application (as I have), you too are vulnerable.

Where Did The Tests Go?

I removed the test projects from the Prism RI and the Composite Application Library projects that go with it. Why did I do that? laziness?

I really thought this simple task would take maybe a long day at most. Stripping the tests away from the start was supposed to help me stay in the time box. It was going to be non-trivial to setup Prism’s test environment, convert the tests, and repackage for distribution to you. I didn’t think I could afford it.

The point of the exercise was to demonstrate how to liberate your application to use an alternative container. I wasn’t trying to deliver a product and there is limited value in tests for a version of the Prism RI that is (a) obsolete and (b) irrelevant to your application.

Unfortunately, this “simple” task kept expanding in scope; it took four long days. Geez like that never happens.

Now that I’m “done” I wish I had those tests back, the UnityBootstrapperFixture in particular. Debugger testing is painful as we all know. Had I committed to automated tests, I would have written something better than the idiotic compiler-directive-based approach to swapping containers. Sure it would have cost me something – a day? – to get it right, a day I didn’t want to spend. But if someone wants to take this further, the tests would accelerate his progress greatly and imbued his efforts with confidence. Mea culpa.

I wonder if some kind soul will restore them?

Happy New Year, everyone!

Posted in Uncategorized | 7 Comments

A Programmer Pilgrim’s Progress

New Jersey, 1962? Vague memories of an entire barn filled with racks of wires and relays like a giant pipe organ. It’s a surplus electronic telephone switch, a predecessor of the Bell System’s 1ESS. A small team of enthusiasts has high hopes for its restoration.  Impressed and baffled, it’s the first computer I’ve seen. I’ll not see another for eight more years.

I am Ward Bell, V.P. of Technology at IdeaBlade, makers of DevForce. DevForce is a product for building multi-tier, data-driven business applications in .NET. It’s kind of like Microsoft’s WCF RIA Services … only we’ve been in production since 2002 with all that implies about focus, experience, maturity, support, features and architecture. We used to have our own ORM, one of the first in .NET. We abandoned that component when Entity Framework was announced; why resist its EF’s inevitable market victory when there is so much need to ease the pain of building distributed applications?

Distributed CRUD apps to be sure. But then most business applications are essentially CRUD + Behavior, aren’t they? A tiny fraction of developers both understand and need message-oriented architectures. The RIA Services perspective – I think of “RIA Services” as a category rather than a Microsoft product – that perspective will dominate Silverlight application development for the next decade at least. Thus spake Zarathustra.

What am I doing on CodeBetter? I’m certainly not here to talk about my product; I’ve got my own blog for that.

I am here because CodeBetter speaks to the software craftsman, the person who is curious about the practice of software development. We want to know “why” as much as “how”. We want to know when to do something and when not to do it. We see programming as a social phenomenon engaging a variety of actors, not as a stunt performed by heroic individuals in isolation. Our craft has a history. What we applaud or disparage today is provisional and contextual. There are no fixed marks – no permanent truths.

Sure, we have convictions and strong opinions rooted in practical experience. But we’re not wizards who’ve mastered a book of spells; we’re seekers, feeling our way forward, exploring better ways to develop software, mindful that the measure of “better” is a function in part of rapidly changing human and technical conditions.

When I read a CodeBetter post, I’m always impressed by the author’s enthusiasm and expertise – yes – but also the passion to communicate and educate. It’s a noble community and I’m honored to have been invited to join.

I come late to my love of the craft. So many of my itinerate years were spent programming unconsciously, showing up for the job, all wit and no wisdom. I’m kind of nostalgic for my old “Mort” self in much the way we can be nostalgic for our teenage selves.

Journeyman programmers are not “those people”; they’re “my people”. I’m freshly reminded of them every time I visit customers. Not all of them are unreachable; most merely slumber. Perhaps we can awaken a few. For the others, we can provide tools, rules, and infrastructure so they can program beyond their competence.

I figure as I write in this space, you’re bound to wonder “who is this guy?” Herewith, a little autobiography.

Lesson #1: Generosity

Poker was my first program, written in APL on an IBM Selectric terminal wired to a System/360 in Poughkeepsie, NY.  In 1966, Tom Watson named Steve Dunwell an IBM Fellow. Dunwell had been the inspiration and driving force behind the “Stretch” supercomputer, perhaps the world’s first supercomputer, delivered three years before Cray’s CDC 6600. His rise, fall, and resurrection is a great story.

As an IBM Fellow, Dunwell had some money and latitude to pursue projects that interested him. Teaching kids about computing was one of those projects. He put typewriter terminals in several high schools, one of them mine. It took passion and selfless dedication to put million dollar machines in the hands of clueless kids. I repaid his generosity with 5 card stud. I think the best it could do was deal cards. That was enough computing for me. Sorry, Steve.

I couldn’t afford college right away. I needed a job. I had no skills, no prospects, and no interests beyond the pursuit of girls and good times.

The fortuitous conjunction of my poker program and my fascination with the Albigensian Crusade lead to a bolt from the blue. The wife of my medieval history teacher worked for Dunwell. She called a Dr. Bill Hagamen, a neuro-anatomist at Cornell Medical School in New York City. He too was a beneficiary of Dunwell’s educational computing vision and he owed her a favor. “Call this kid and see if you can use him.”

I stumbled through the interview … a complete disaster. I couldn’t remember a thing about my poker program or APL. He almost hung up but I begged to see him and try again. I have no idea why I begged him or why he accepted. But a few days later, after cramming “A Programming Language” by Ken Iverson, I was sitting at his kitchen table in Long Island trying to convince him I knew enough APL to be useful.

I didn’t fool him at all but there must have been something he liked about a  nineteen year old, long-haired, hippie kid who would try that stunt. More likely he needed to payoff the favor and he didn’t have any money for programmers anyway. Over the next few years he’d hire a taxi cab driver, a Ph.D in Slavic languages, a street musician, … just about anyone who’d work for dirt and flashed a little intelligence.

Dr. Hagamen was cheap by necessity, not by nature. When I met him he was still funding his work with grants. Grant money is uncertain; even when awarded, you can’t be sure when it will arrive. “Write the grant proposal for work you’ve already done; the money funds the research results that are the basis for the next grant”.

Live this way and you learn to spend carefully and scrounge for everything. He lived alone, subsisting on cigarettes and McDonalds as far as I can tell.

His neurological research depended on cats. Unlike the human brain, the cat brain hardly varies from subject to subject; it’s a stable specimen for anatomical research which, at the time, consisted of surgically poking at interesting structures to see what happened. The top floor was a vast mob of cats in cages, blinded and lamed in the course of his work. Cruel as this sounds he was not a cruel man; they purred and rubbed themselves against him with no sign of pain. He had gathered each one himself, walking the alleys of New York by night with his cloth cat collection bags: “press down on the neck just above the shoulders and they’ll push back with their fore legs, immobilized” he advised; “Then whip them in one stroke into the bag.” That’s scrounging.

We were just cats of a different color, scrounged from the streets of New York. We too purred every time we saw him. He loved each of us as individuals, listened to our stories, shared his own, laughed freely between long drags on endless cigarettes. If the toe of my shoe pointed slightly out he’d note that I’d sprained my ankle slightly … as indeed I had, playing basketball the night before. He became a second father to me. We had long conversations about everything.

He taught gross anatomy. The door to our computer lab opened into an adjacent dissection room where Dr. Hagamen showed students the body’s neural pathways. We met there often to discuss some forthcoming feature while he prepared for tomorrow’s lecture. I can still see him, bare hands deep in a cadaver’s chest, absent mindedly tying little white flags around nerve bundles while we talked. I never got used to that, pretending not to stare at the hollow shell of a human being, tanned leathery brown from its bath in formaldehyde. We stood amidst rows of them in various states of disrepair, limbs wrenched into impossible positions, parts meticulously tagged for display. Didn’t bother him at all.

Usually we talked about the work. Dr. Hagamen (he was always “Dr. Hagamen”, never “Bill”) had tired of neuroanatomy. Natural language processing was his passion now and for the rest of his life. We were writing a system for Computer Aided Instruction (CAI) to supplement the lectures in a medical student’s training. The program typed out questions, say, about the muscles of the eye. The student answered in full English sentences. The program determined what he’d said and chose what to ask next based on its “interpretation” of the student’s answer: if deemed correct, on to the next question; if it was a common error, on to a revealing query series; if flat wrong or unintelligible, ask for clarification. No multiple choice, no cheerful “right” or excoriating “wrong” answers. If you knew the muscles, you were through in minutes; if you didn’t, the program could lead you for more than an hour through a maze of enlightening statements and follow up questions.

Our teaching model was Rogerian psychotherapy. Dr. Hagamen had translated Joe Weizenbaum’s ELIZA (1966) into APL. That was the inspiration for our achievements in simulating “normal conversation”; we applied some minimal grammatical analysis, extracted key words matched to a constrained subject-matter context, and leaped to conclusions about what you had probably said. It worked surprisingly well and I think is still the foundation of most CAI to this day.

We knew this wasn’t how language actually works in humans … no more than airplanes simulate how birds fly. The facade of human conversation collapsed quickly as the vocabulary grew, the context expanded, or the sentences became paragraphs. We wanted to apply more intelligence and fewer statistics. We read Chomsky, hoping to find the deep structures of language and enshrine their algorithms in APL.

We didn’t get far. The search, however, was intoxicating, especially for a kid fresh out of high school. It seemed to me I was doing something important; we were pushing against the frontiers of knowledge and I was part of it.

He made us part of it. He put our names on the papers he published. Each of us had a moment or two in the sun. There I am, listed as a co-author of “ATS in Exposition”, Computers in Biology & Medicine, volume 3, 1973; got my first academic citation before I’d even entered college. I hadn’t written a word of it.  I guess I had contributed in some small way just by being on the team. He wanted to share the credit with all of us.

Looking back I understand now a little better about what “team” means. We were more than a group. We knew about each other’s lives – family, friends, pleasures, peeves. We played together as much as we worked together. We may not have been great at what we did, but we were full of common purpose and proud of what we did. We shared our code as we would share a beer, hiding nothing.

And were we ever close to our customer. So close we couldn’t have thought of it that way. Dr. Hagamen was happy to be the worst coder among us (smart of him to let us think so) but he was our leader, our friend, and we tried never to let him down.

I am convinced that commitment to purpose and fellowship trumps anything to be gained from smart people, “best practices”, great architecture. Get to know your team intimately and authentically. Disappointments are inevitable but your colleagues will fight like cornered rats to avoid them. Share the credit, absorb the blame and your prospects for success improve beyond measure.

The cigarettes and quarter-pounders finally caught up with him. He died from cancer in 2007 at 82. I’d long since gone west and fallen out of touch. The others hadn’t.

The news found me across the decades and broke my heart. I grieve for him now. In thirty years, who on any of my teams since will grieve for me? It’s a question I ask myself now and it goes straight to producing productive teams. Generosity of spirit, inspired loyalty, a learning organization … whatever my failings as a developer, this I can build.

Lessons #2: Productivity

Dr. Hagamen didn’t have to worry about hiring a complete loser. The APL language itself weeds them out. Your program either worked or it didn’t and there was no waiting around for days full of excuses. A few lines told everything about you and your potential.

You simply can’t fake it in APL. Every expression is a parade of equal parts alphabetic and hieroglyphic characters evaluated from right to left. Conway’s Game of Life can be written in a single, impenetrable line. You want to do away with ceremony? You want zero noise? You want the maximum bang for your keystroke buck? APL is your language.  Ruby? Boo? They’re chatterboxes. In APL you can pack a ton of functionality into 32k of main memory, the extent of our universe in those days.

Unfortunately, APL deserved its reputation as a “write-only” language; the annual contest for one-liners of maximum obscurity was a highlight of every ACM APL conference.

But it was (and remains) a serious language, a forerunner of the functional programming languages becoming popular now. Skim Ken Iverson’s own Turing Award Lecture, “Notation as a Tool of Thought” and discover your unworthiness. This is genius almost unknown today.

APL is interpreted which, combined with its unequaled power and economy of expression, enabled productivity such as had never been seen … and would not be seen until this century. While everyone else was presenting their boxes of 80-column cards to the guardians of the raised floor, hoping to squeeze in one or two runs per day, we were merrily tapping away at our terminals, cranking out several new applications a week.

I learned the power of iterative development writing APL. No interminable design documents for us. You had an idea; you wrote it and shipped it. It was cowboy programming but who knew? Who cared? Everyone’s programs were rife with bugs in those days. We could find ours, fix, and release again in minutes while the Fortran guy was still waiting for the band printer to burn through a box of paper with his core dump.

APL swept through the IT shops of New York financial houses. Morgan Stanley, Merrill Lynch, American Express … I would one day write APL for all of them. They still use APL! APL’s mathematical heritage had nothing to do with it. I suck at math. Fortunately I never needed more than high school algebra. I wrote applications to find things, watch things, and count things; I was solving the same kinds of business problems we work on today. APL dominated because it was incredibly productive.

On the street they hated to wait. Time-to-market was everything. The half-life of an application was a year or two. Maintainability was an after-thought; overpay the developers to stick around and everything would be fine. You only needed one or two … compared to the army of drones it took to write it in any other language … assuming they could get it done before you lost interest. Had there been such a thing as well-tested code, the cost to produce it would never have overtaken the benefit of moving pell-mell. Quality was a distant second to Functionality … and rightly so.

In time I learned to value the stability and maintainability of well architected, readable, code written in compiled, statically-typed languages. Today’s IDEs and fast compilers have narrowed the productivity gap. It’s no longer a straight-up trade between productivity and maintainability. I wouldn’t write in APL now even if I remembered how.

I remain receptive to the “git ’er done” message. It’s pointless delivering a properly architected and tested product later than it’s needed. The budget will be gone. The opportunity will be gone. Technology debt is a great thing when there is big return for short term debt. This I learned during my first twenty years of programming.

Our present challenge is to marry speed and sound practices.  That was impossible when I started; I believe it is possible now. We have to keep our eyes on both … and I intend to do that in my posts here on CodeBetter.

Lesson #3: Suspect all arguments about Performance

The quest for maximum performance in minimal space ruled our days. We were programming in a phone booth: 32k memory, 30 characters-per-second networks, tape drives. One of us, David Linden, discovered that the integer ‘1’ occupied 4 bytes in memory while the variable name “ONE” took only three; he could shave hundreds of bytes from the program simply by substituting ONE for ‘1’ and “TWO” for ‘2’. We promptly converted all of our programs to spare those precious bytes. We might have patented the process had there been lawyers around to guard our “intellectual property”.

We thought about algorithms, not methodology.  Dijkstra was unknown to us; we didn’t know that GOTOs were bad style We knew that performance stunk for any kind of branching at all so we avoided it where possible, favoring the APL equivalents of map and reduce. We had no notion of “style”. We had “idioms”, the best known being “((V ι V) = ιρV)/V”, which removes duplicates in the vector, V. “V” itself was a popular enough name – second to ‘X’ perhaps – and we’d use it everywhere. Any function or variable name over four characters attracted the gravest suspicion; it took too much space and cost more to fetch.

Thank goodness we don’t have to write this way any more. At PDC I heard a speaker say “our hardware is 50,000 times faster but our programs are only 5,000 times faster.”  As if that were a bad thing. It’s not bad at all. I used to argue with people who insisted you should program only in assembler because higher level languages – Fortran, PL/I, APL – could never perform as well as properly written assembly code. No one makes that particular case anymore. It’s obvious now that we’d never get much done that way even if it were true. It also happened to be false much of the time for even a modest body of code; then as now, compilers regularly beat good assembly coders.

We prioritized performance because we had to; the program died or ran out of memory without those tricks. You’ll note that David measured the optimization before we employed it.

It galls me to hear someone argue for “better performance” before anyone knows if it will matter. Almost as bad is the phony speed derby down a short track when we know we’ll be running a marathon. Consider the smarty pants who proves that a Data Reader executes a simple query many times faster than an ORM. No kidding. Of course the application won’t run that query more than a few times all day and when it runs, no one notices the difference between 300ms and 30ms. Meanwhile, we discover that network latency is the dominate factor. Reducing trips to the server, each payload packed with a rich object graph, yields a vastly more responsive experience than the Data Reader Guy can dream of. Not to mention that Mr. Data Reader will waste months chasing bugs at the expense of building business value.

You want to be sensible. Synchronously loading a 100,000 records before you show the first screen may work on the LAN but it will never fly over the internet. Reason and experience can spare you much heart ache. A little scratching on the back of the envelope can clarify issues and identify threats. Otherwise, we’re far better off writing clear, clean code … benchmarking … and tuning the hot spots as we find them.

“Duh” you say? I’ll keep talking about this until my customers stop arguing about performance prematurely or ignoring it altogether.

Lesson #4: Read Code … Lots of it

We were all self-taught back then. In our little lab on East 68th street, we learned by reading each other’s code. Maybe we worked in a vacuum but no one I knew thought about software methodology. The first “Software Engineering” conference was held in 1968. David Parnas coined the terms “modularity” and “information hiding” in 1972. We didn’t know about any of this. We had few books and publications to consult: a couple APL reference books, the Transactions of the ACM, the IBM Systems Journal, and Knuth.

An eye-opener for me was Fred Brooks “Mythical Man Month” (1975), a landmark then and forever relevant. Brooks described it as "my belated answer to Tom Watson’s probing question as to why programming is hard to manage." Its many lessons are blithely ignored to this day. Try explaining to your twenty-something manager that “adding manpower to a late software project makes it later.

Brooks woke me to the idea that programming is a social phenomenon to be studied and reasoned about. Then I went back to sleep for another seven years.

We read code. Not books about code. Not magazine articles with code samples. Production code. Code written by colleagues and later by customers. “Good” code and “bad” code.

A lot of what we thought was “good” code we’d now regard as “bad” code. The converse is not true: what was bad then is worse today. And there was truly awful code out there. I ought to know; I wrote plenty of it.

I wish we had had the books, articles, blogs, manifestos, and conferences readily available to any developer today. I would have learned faster and avoided mistakes that seem obvious to me now. I won’t fetishize a prolonged experience in ignorance.

On the other hand, I don’t believe you can read your way to competence. You have to write a lot of code before you get decent at it. You have to read even more code before your writing gets good. In this respect it is like any profession. We learn by doing and we improve by watching others do it.

Don’t get stuck reading just one person’s code. Don’t get stuck in one school of design either. Look around. Try another language. See how different applications, different developers, and different customers create conditions and constraints that shake your assumptions. As Han Shan says “There is no path that goes all the way”.

No one path for me.

… Next Installment?

So much for a brief intro. Suddenly I’ve got a memoir going.

If my introductory post generates favorable interest, I’ll keep going. If it generates outrage and alarm, I’ll stop!

A “next installment” could cover:

  • The Reluctant Programmer – how I discovered I was a programmer while striving to be something else.
  • The Itinerant Programmer – life as a job-hopping consultant and what I learned about making a quick impression and grasping the customer’s business, “Show me the data and I’ll tell you what your application does”. Hubris and infrastructure.
  • The Corporate Programmer – “10 years before the mast” Or “settling in at GE”, How long does an application last? Cobol follies.
  • Never hire a friend – Oops
  • Hiring a programmer – Ravishing beauty versus pain-in-the-butt
  • Life on the other side: becoming a customer of IT
  • “If it makes no business sense …” – my Dot Bomb moment
  • Starting a product company
  • Re-starting a product company

Until we meet again …

Posted in Uncategorized | 16 Comments