Trick-hot command pattern in C#

I’m working on some code that needs an undo feature, so naturally I turned to the command pattern.  I pulled out GoF to glance at their naming conventions and started to type, all the while thinking “there has to be a better way to do this.” Here’s what I think is a better way.

Recall that the command pattern specifies an abstract “Command” type with an Exceute method. This is only needed in languages without first-class functions: C# gives us delegates, which are pretty much equivalent in this case.  So we’ll skip the custom class and just use them.

But the extended, more useful form of the pattern also has an UnExecute method, used for undo.  This lets you push the commands onto a stack after executing them.  Undo is then simply a matter of popping the most recent command off the stack and UnExecute()ing it.  The command instance retains enough state information to undo what it had previously done.

We can do all that through the clever application of closures.  I’ve chosen to implement the commands as static methods, but they could also be implemented as regular methods, even virtual if you’d like to be able to route around to different implementations. Here’s a fictitious example:

static class Commands
    public static Action HAlign(Item stationary, Item movable)
        int oldX = movable.X;
        movable.X = stationary.X;

        return delegate()
            movable.X = oldX;

Executing the command is just a method call, and enabling undo is as simple as pushing the returned Action (just a delegate with no parameters or return type) onto an undo stack. (Stack<Action> will do nicely) The returned delegate captures, via closure, all the state in needs for undo to work properly.

That’s it! There are a few small land-mines in the details of how closures work (especially w.r.t. non-local or iteration variables), but the general technique is very simple.

Two cool things (cappuccino, github)

Cool thing 1: Cappuccino.  I’m sure this is well known by most by now.  I’ve been playing with it in my copius free time and continue to be impressed.  I’m excited to be able to use Objective-C in the browser – I’ve always thought it was a nice language, despite my lack of experience with it.  In particular, dynamic message dispatch is a perfect fit for GUI programming.

Cool thing 2: github.  While playing with cappuccino, I thought I’d fix a few bugs.  So I made a github account and cloned the full repo.  The clone took about a half second.  Really.  The collaboration model on github just decimates all the commercial systems I’ve used, not to mention cvs and svn.  This is what sourceforge always should have been.