Expression Trees

If you’re anything like me, you’re lazy.

I choose a lazy person to do a hard job. Because a lazy person will find an easy way to do it.

– Bill Gates

Apparently, in the world of programming, being lazy is a virtue, so maybe by passing this along I’m being virtuous?!?

I came across a library I had to implement this week that had function calls down to some hardware. Now since this library was a wrapper for a C (or C++) library, and whoever wrote it didn’t want to put a lot of work into it, every function called would return an ErrorCode enum.

Now if I was to be a copy and paste wizard, I’d just write myself about 20 of these

var errorCode = HARDWARE.GetSomeInformation(1, true, ref why???);

if (errorCode != ErrorCodes.None)
    Throw new CustomErrorException();

Obviously, that sucks. Nobody wants to do this. If you want to do this, you’re crazy. Even if you’ve got all the time in the world, or you’re a Regex master, or you’re using a tool called NimbleText you still shouldn’t do this. I think this is what people refer to as brittle code. If anything ever changes, or you realize you wanted to do something else with that error code, you’ve got to change it in 20 places (or more, how big is this library anyway?).

I decided to wrap this error call in a nice function delegate that would allow me to put all my ErrorCode handling in one place and just get on with stuff. Here’s what I ended up with

..
HARDWAREWrapper(() => HARDWARE.GetSomeInformation(1, true, ref why???));
..

private void HARDWAREWrapper(Func<ErrorCodes> functionToCall)
{
    var errorCode = functionToCall();

    if (errorCode != ErrorCodes.None)
        Throw new CustomErrorException();
}

OK, much better, now if anything in those function calls changes generically, or I decide to add more information to my exception we’re all good. It’s just one spot. Single responsibility principle? Not sure if that exactly counts, but my goal today is to sound smart by using lots of programming words (let me know how you think I’m doing).

So, here we go with the downside of this, since this is a generic call, it’s a little harder to figure out what exactly caused the exception in the first place. Since any code could be in that function (as long as it returns ErrorCodes) it’s a little harder to debug, especially if this is in the field and all.

Luckily I came across something pretty sweet called an Expression. I can wrap the Func<ErrorCodes> in this Expression to allow me access to the actual text of the function for debugging purposes. I’m sure that’s not what it was designed for, but it’s what I’m using it for today. Here’s the code –

..
HARDWAREWrapper(() => HARDWARE.GetSomeInformation(1, true, ref why???));
..

private void HARDWAREWrapper(Expression<Func<ErrorCodes>> expression)
{
    var functionToCall = expression.Compile();

    var errorCode = functionToCall();

    if (errorCode != ErrorCodes.None)
    {
        Logger.LogtoFile(expression.ToString();
        Throw new CustomErrorException();
    }
}

As you can see, the call to the function doesn’t actually change, even though it’s wrapped in an Expression, but it does allow you to log the function delegate contents to file. With Expression.ToString() I get access to the line HARDWARE.GetSomeInformation(1, true, ref why???) in text format.

Awesome. OK, that’s all I’ve got. If anyone out there is listening, let me know what you think!