Code Beast

Delegates and Visitors

October 3, 2007 · 9 Comments

The GoF visitor pattern is useful but awkward. The usual c++ or Java-y versions typically involve some kind of visitor interface which your visitor must subclass. Java somewhat mitigates this with anonymous classes, but not fully. In C#, if we’re clever with the use of delegates, we can make tasks like tree traversal look about as simple as iteration.

Let’s start with a simple tree class:

class Node {
    Node[] children;
}

We’ll implement a depth-first search using the visitor pattern. Using delegates, we can eliminate the need for an additional class:

class Node {
    public Node[] children;

    public delegate void VisitorDelegate(Node currentNode);
    public void Traverse(VisitorDelegate visitor)
    {
        foreach(Node n in children)
        {
            Traverse(n);
        }
        visitor(this);
    }
}

This is a pretty simple recursion, and really isn’t anything special. The way delegates are typically used, there is still an additional method required for the delegate to be called. But with C# 2.0, we have the opportunity to use anonymous delegates. This is where we can write some really slick code:

void TestTraversal()
{
    Node root = GenerateTestTree();

    int nodeCount = 0;
    root.Traverse(delegate(Node n)
    {
        nodeCount++;
    });
}

The really cool thing about this is that, since anonymous delegates can act as closures, our visitor can pull in the nodeCount from the surrounding environment. This makes for a very succinct version of the visitor pattern.

Technorati Tags: ,

→ 9 CommentsCategories: c#

Properly Abstracted List APIs (in C#)

September 17, 2007 · 2 Comments

We frequently encounter APIs that take lists of objects as parameters. The code behind the API will likely want to know something about those objects. It might sort them or extract some metadata and then process them. It may return a list of the objects with additional data. The question at hand is: how should the API get the data it needs about those objects?

Presented below is an elegant solution which preserves separation of concerns.

In considering this problem, we’ll use a simple (read: contrived) example: a chart drawing API that needs an X and Y data point for each item in the chart. The client has a number of StockQuote objects it wishes to plot, defined as follows:

class StockQuote
{
    public float price;
    public DateTime date;
}

Suppose further that later on I want to be able to react to user interaction with the chart and obtain the relevant StockQuote object.

Simple Approach: Data Objects
A typical approach would be to define a data structure with the information in question. For example:

library:

class ChartPoint
{
    int objectId;
    public int x, y;
}

Chart CreateChart(List<ChartPoint> points);

client:

List<ChartPoint> points = new List<ChartPoint>();
foreach(StockQuote quote in quotes)
{
    points.add(new ChartPoint(quotes.IndexOf(quote),
        quote.date.DayOfYear,
        quote.price));
}

CreateChart(points);

This works, and is explicit, but is very wordy. It’s very easy to implement on the library side, of course. But I’ve got to create an intermediate list of this other type on the client side, which adds three lines of additional code on top of the call, plus an intermediate list. It also imposes this requirement that I have an Id to refer to my object, so I can know which one is which when later interacting with the chart. That’ll be another layer of lookup – this doesn’t feel right at all.

OO-Approach: Interfaces
Many would suggest the following method:

library:

interface IChartable
{
    public int X { get; }
    public int Y { get; }
}
Chart CreateChart(List<IChartable> points);

client:

class StockQuote : IChartable
{
    public float price;
    public DateTime date;

    public int X { get { ... } }
    public int Y { get { ... } }
}

ChartAPI.CreateChart(stockQuotes);

The actual invocation has improved, and I no longer need the Id field, since I’m passing in my objects directly. But now my class has to implement this ‘chartable’ interface that none of the rest of the code actually cares about. That doesn’t feel right either. We should be able to do better.

Generic Approach: Accessor Delegates
The question to ask is: what is the fundamental thing the library actually cares about? What is the core of the problem? The answer in this case is: for each object, what is the X value and what is the Y value? Or to phrase it differently: how I extract the values from the object in question? Lets provide that information directly.

library:

delegate int CoordinateAccessDelegate(object o);
Chart CreateChart(List<object> items,
    CoordinateAccessDelegate xAccess,
    CoordinateAccessDelegate yAccess);

client:

ChartAPI.CreateChart(quotes,
    delegate(StockQuote q) { return q.date.DayOfYear; },
    delegate(StockQuote q) { return q.date.price; } );

Since what we want is the way to access the X and Y data, we’ll give it exactly that: an access delegate. In this way, the chart library doesn’t particularly care about the format of the data I’m using, nor does the rest of my application care about the requirements of the chart library. And I avoid the painful copy step of the data-centric version.

A hidden benefit of this approach is revealed later, when the chart library needs to return to me information about some user interaction. It can do this now in my own terms, with my own objects, rather than by using some structure with an id field that I have to map to my object.

Some will have correctly observed by now that this is the same technique used to provide a sort comparator. This is exactly right! Understanding the technique and realizing it may be used elsewhere is the entire point.

Of course, this technique is not appropriate for all problems. If a large number of accessors are required, it probably shouldn’t be used. The goal is a literate API, one in which the invocation parameters represent the data that is actually required.

Technorati Tags: , <a

→ 2 CommentsCategories: c#

Vertical Integration

August 8, 2007 · Leave a Comment

Apple today announced a lot of new things – a sexy computer, a spreadsheet, and a new version of iMovie. A complete rewrite, according to the reality distortion field. It’s got this cool feature where you scrub the mouse across a video and it updates according to where it is. They also have a neat way to decompose things by scene very quickly. Watching the demo video got me thinking: how would I go about doing that? Really, it’s an impressive technical feat, dealing with all that data so immediately.

And here’s the thing: I don’t think I could do it. Not because of any inability on my own part, but because I don’t have the tools. I think there are exactly two companies today with the technical ability to pull off something like that: Apple and Microsoft. They each have:
– An OS
– A video stack
– A DRM system
– A whole suite of applications (roughly 1:1 corresondence)
– An application development stack
– An IDE (or five)
– The source code for all of the above
– The people who wrote all of the above

Any reasonable idea I can come up with for doing the kind of thing done by the new iMovie involves changing the video stack. And since I can’t change the video stack, since I don’t work for Apple, I’m out of luck.

Apple and Microsoft clearly have an advantage by controlling the entire software vertical, but I contend that it makes applications such as this downright impossible. Microsoft in particular has a long history of releasing one API and writing their own applications using another.

Where is there hope for innovative apps? There’s one more vertical set of code I haven’t mentioned: open source. It’s not easy, but the tools are there to do what needs to be done. The only way to do any kind extensive innovation on a desktop app is by basing it on open source technologies. Apple and Microsoft simply cannot be fought on their own turf.

Technorati Tags: ,

→ Leave a CommentCategories: opinion

Virtualization Heaven

August 6, 2007 · Leave a Comment

I recently got a new workstation with lots of memory (3 GB) and a big disk (750 GB), and it has significantly improved my life. Here’s how:

1) Since we’ve got MSDN, I get Virtual PC for free. Not as cool as VMWare, which has neat ways to manage the changes to your VM, but still good enough for me.

2) I did a patched up XP install and save the VM definition + the disk (vhd and vmc files) in VMs/Base XP. I seem to remember having to hack up the .vmc file to have it use a relative path to the disk. The disk is named ‘disk.vhd’ to save me work.

3) Whenever I want to do something possibly invasive, like test a beta of Visual Studio or something else that I would be pretty stupid to do on my main dev box, I simple clone the directory, rename the files, and go from there. The copy takes about 5-10 minutes, depending on what else I’m doing at the time.

4) I’ve also got a ‘Base XP Dev’ image with my development environment all set up that I can use for extended debugging sessions without having to tie up my normal environment. Particularly useful when doing a long-running automated test on an old version, when there are outdated COM APIs (I know, I know).

I don’t think I’m ready to go full-on virtual yet. I tried that once, but the responsiveness of the VM just wasn’t where it needed to be. Immediate feedback is very important to me, since I tend to move pretty fast through systems that I know well. Maybe someday when I get a quad core box and the VM apps can spread across multiple cores, I’ll give it another try.

In summary: virtualization makes me happy.

Technorati Tags: ,

→ Leave a CommentCategories: workflow

Standard is Better than Better

May 9, 2006 · Leave a Comment

Neal Ford wrote some interesting things about naming conventions: Eating Sacred Hamburger. And even though I agree with everything he says, I think he draws the wrong conclusions.

He first argues the relative merits of various naming conventions, preferring ruby_case to CamelCase, especially for very_long_and_drawn_out_method_names. It think he hits it right on the button, though I personally prefer lisp-case for very-long-and-drawn-out-method-names, since it’s easier to type.

He also argues against Hungarian notation, which I agree is a blight upon all that is good and green. And the IInterface notation is also a little silly, but…

It’s convention. We should follow the convention.

Did I just say that? Giving up progress, and readable code, just to do it in the same way it’s always been done?

Well, yes. Remember in C++, when you were using STL sometimes and MFC sometimes? They used different naming conventions entirely. And you could never remember what goes with what. Intellisense helps with that some, but it’s still awkward. And what about reading the code? While it may be a little clumsy to read long names in camel case, it’s far better to have the formatting match. The overall codebase is more beautiful as a result.

So, I say: bring on the IInterfaces! At the end of the day, I don’t care how we name things as long as we name them the same way. Or, to quote my boss: “standard is better than better.”

(Maybe they got rid of Hungarian notation not because it sucks (which it does), but because they couldn’t get everybody to agree on it. A convention is only useful if everybody does it. And right now, in C# at least, everybody does do it. It’s great for an old C++ hacker like me. So please, don’t break it!)

Technorati Tags: , ,

→ Leave a CommentCategories: c#

Essential Windows debugging tools

May 3, 2006 · Leave a Comment

I’m no Windows dev expert, but I’ve been doing it long enough to have collected a set of tools that go with me. They sit in a nice little rectangle on my desktop, and I also have a USB key to carry them with. Not all people know about them though, or maybe have seen them and haven’t learned to use them. I recommend at least familiarity with the following:

  1. OleView I do a lot of COM work. I try to make it go away, but it keeps coming back. As such, my first choice of debugging tool is good old oleview. Every time our install breaks because of some munged dependency, the first step is to fire up oleview and check that all needed objects are registered, and that they can all be instantiated. That last bit is non-obvious but very cool – when you expand an object in the list and it turns bold, the object is actually being instantiated. So just expanding each one you care about is a good smoke test.
  2. Filemon Everybody probably knows this one already, but it’s so important that I can’t leave it out. If you haven’t used it, do yourself a favor and get familiar. It can be used for any program running on windows, so it’s good even for you Java folks. My strategy with Filemon is usually to first figure out a concise way to reproduce the problem, then do a specific session to see what’s happening. I usually forego the filters (remember the COM I’m running from? Lots of out-of-process servers there.) and just start/stop event logging at the right times.
  3. .NET Reflector Ah, what would we do without Lutz Roeder? I’ve used this to read my own (decompiled) code while working through a bug on a test machine. Saved me some walking back and forth at least, plus I felt like such an incredible badass doing it. It’s also good for determining that the localizer sent you back an assembly built with .NET 2.0, when you very clearly asked for 1.1. (A co-worker’s find, not my own)
  4. Spy++ Are you noticing a theme here? All the old tools that let us observe the bowels of the system are still useful. Sometimes you just want to watch the messages fly by, and Spy++ is still the way to do it. ManagedSpy may be worth a look too.

As mentioned above, what I find compelling and useful about these tools is that they take a step away from what your software is supposed to do (that’s what the source is for) and let you know what it’s actually doing. There’s an entire class of subtle bugs that such insight enables you to diagnose – the first two tools have saved my ass on multiple occasions.

Technorati Tags: , , ,

→ Leave a CommentCategories: debugging

Easy C# Memoization

May 2, 2006 · 3 Comments

I called it MagicCache at first, thinking I’d come up with something new and cool! But, as usual, I’d actually just forgotten the name.

Memoization is a useful but intrusive technique. It’s the kind of thing that I want to be able to wield around my code and put it where I need it, almost as a configuration-time parameter. So I’m not quite satisfied with just writing the code myself each time I need it. This is a perfect case for AOP.

The approach I took was not to use an existing AOP framework, since I think that would freak my coworkers out a little, but rather to do my own simple system. It uses the fantastic DynamicProxy (as do all C# AOP systems I know of) to inject code, and I use a custom attribute to mark the invocations I care about. The result is quite pleasant to work with:

[Memoize]
virtual int Sum(int a, int b)
{
    return a+b;
}

Or, in more complicated cases:

[Memoize(MaxCount=100)]
virtual object BuildObject(string paramA, int paramB)
{
    ...
}

I like this particular method because the caching policy is nicely separated from the actual logic, but has enough proximity to see what’s going on. And I don’t have to write the caching code again and again, which means I’m free to enhance the general caching algorithm.

Of course it’s not quite as easy as all that. Memoized methods must be virtual, for DynamicProxy to be able to intercept the invocation, and the object in question must be wrapped in a proxy object. In my case I wrapped it all up in a single method call, Memoizer.CreateProxy(obj). For objects that are already built in a factory this is not problem at all, but sometimes it’s kind of inconvenient.

I’ve also added the ability to treat returned strings as paths to files which are deleted when they are removed from the cache, though I haven’t thought through it well enough to be generally useful.

Technorati Tags: , ,

→ 3 CommentsCategories: c#

mbUnit

April 20, 2006 · Leave a Comment

I would like to take a moment to espouse the wonders of mbUnit. It is to NUnit as C++ is to C, as Perl is to Bourne shell, as Milk Duds are to milk. That is, the former supports the same basic principles as the latter, but gives you more rope with which to hang yourself. And really, who can resist that?

It supports the same "idiomatic" syntax as NUnit, which is a good start, since that's really the only way to do unit tests in C#. And you can do the usual TestFixture/Test stuff, which works, but is kind of clunky and unwieldy.

But the mbUnit folks have taken it a step further. The old way always involved writing cumbersome loops over sets of input and trying a particular call/assertion for each of them. Boring, repetitive, not ultimately traceable. But by allowing tests to have parameters and creating a configurable binding phase, all that goes away. It works like this:


[RowTest]
[Row(1,2)]
[Row(3,4)]
void TestSomething(int a, int b) { ...

That's just the binding, straight up, as a set of rows. Simple but useful, and far cleaner than the alternative. In the testrunner, you'll see that as two tests. This really is the right way to do it, I think, since you can easily trace failed tests to a particular set of inputs. But it really gets cool with CombinatorialTest. I find myself most often using the trivial case:


[Factory(typeof(string)]
public IEnumerable InputFiles()
{
return System.IO.Directory.GetFiles("inputDir");
}

[CombinatorialTest]
public MyTest( [UsingFactories("InputFiles")] string filename )
{ … }
Now that's downright great. And there are all kinds of other useful generators, like UsingValues and UsingLinear. With multiple parameters, Combinatorial test evidently combines them in some significant way, but I honestly don't understand the whole thing. I'm just willing to let it work.

My only complaint? I haven't yet found a good project template for visual studio. I'm sure I could make one, but my laziness is still fighting itself on that one. I know, it's supposed to be easier in VS2005, but my wounds have yet to heal from the last attempt.

→ Leave a CommentCategories: c# · testing