james mckay dot net
because there are few things that are less logical than business logic

To throw or not to throw? Non-exceptional error conditions

I’ve said before that the general advice that “you should only throw exceptions in response to exceptional conditions” is bad advice, because it is ambiguous and unclear as to what exactly constitutes an exceptional condition. But nevertheless, there is a valid point behind it.

The point is that exceptions are (a) slow, and (b) painful to step through in the debugger.

This means that if there are error conditions that crop up frequently, you will want to handle them without an exception being thrown wherever possible.

The classic example here is, of course, attempting to parse an integer. This is why .NET gives you the Int32.TryParse method. If it is provided with an invalid input string, it returns false instead of throwing an exception.

Now there are two important points to note about Int32.TryParse.

First: it returns false only in response to a single, specific error condition: namely, bad user input. Any other failure mode should still throw an exception. This is the case with the overload of Int32.TryParse that also takes some localisation and formatting parameters, for example.

Second: its name tells us that it returns an error code in response to this specific condition. If it didn’t have that Try... prefix, it would, as Yoda said, be a case of “Do or do not. There is no try.” This means that the meaning of exceptions — that the method can not do what its name says that it does — is preserved.

Third: it is provided alongside an equivalent method, Int32.Parse, that throws an exception as normal. This gives consumers of your API a choice about which method to use.

Fourth, and most importantly, it is not implemented by throwing and re-catching exceptions. If you write a method like this, you are doing it wrong:

public bool TryParse(string input, out int output)
{
    try {
        output = Int32.Parse(input);
        return true;
    }
    catch {
        return false;
    }
}

Rather, you should do it the other way round:

public int Parse(string input)
{
    if (input == null) {
        throw new ArgumentNullException("input");
    }
    int result;
    if (Int32.TryParse(input, out result)) {
        return result;
    }
    else {
        throw new FormatException("The parameter 'input' was not in the correct format.");
    }
}

Why should this be? Remember that exceptions are expensive both in terms of execution time and stepping through them in the debugger. If you are implementing Try... methods by wrapping other methods in a try ... catch block, you will be losing the benefits of having a Try... method in the first place.

Recommendation: Use this pattern whenever you are taking user input that may or may not be valid. But do not use this pattern for error conditions that are not a direct result of invalid user input.

Returning.To<.NET>()

Over the past fifteen years or so, it’s been trendy for .NET developers to write blog posts announcing that they’re “leaving .NET”. In this blog post, I am going to do the exact opposite. After a two year hiatus, I will soon be working once more with Microsoft technologies.

At the end of May, I will be leaving the Parliamentary Digital Service.

I’ve been working for the Houses of Parliament for nine and a half years now, and it’s been an awesome and exciting privilege. I’ve had a ringside seat at three General Elections and the Brexit referendum. I’ve not only seen the political process close up, I’ve had to translate it into computer code. I’ve learned things about the ins and outs of the running of the country that I never even knew existed. It’s felt like Alice in Wonderland, but it’s been an amazing time.

I will be having a week’s holiday and then starting a new job at JFA Systems, a small company based in Horley that specialises in creating software for the travel industry, on the fourth of June.

What kind of .NET shop?

Some people may find it a bit curious that I’m returning to .NET, given just how scathing I’ve been in the past about some of the things that you see in the .NET ecosystem.

But not all .NET shops are places that insist on being spoon-fed by Microsoft and don’t let you think for yourself. Not all .NET shops still think that stored procedures are a Best Practice and refuse to move forward. Not all .NET shops demand that you rewrite perfectly good Python build scripts in unmaintainable MSBuild gibberish for no reason whatsoever other than That Is How Microsoft Wants You To Do It. Not all .NET shops are hostile to open source or interacting with the wider software development community.

Certainly, I left the interview at JFA Systems with the distinct impression that they were on the same page as me about this. I was every bit as scathing about the SFBMs and cargo cultists in my interview as I have been on my blog — and they loved it. When they offered me a job later in the day, I had no hesitation in accepting it.

One thing in particular that I’m looking forward to is getting back into full-stack development. For most of my career I’ve worked with a healthy mixture of front-end, back-end and API development as well as Ops/DevOps/deployment. In fact, the original intention two years ago, when we first started prototyping a continuous delivery pipeline on AWS for the new Parliament website, was that I should get some experience with modern DevOps techniques and cloud platforms to augment my skills and experience as a full-stack developer. But things changed, and the team I was on ended up becoming first and foremost an Ops team. They’ve valued my contributions as a developer, and as such making it more DevOps than just plain Ops, but I’ve never been entirely happy about becoming a DevOps specialist.

So long, and thanks for all the jerk chicken…

If there’s one thing that that I’ll miss about working in Parliament more than anything else, it’s the House of Commons catering department’s most popular dish — jerk chicken with rice and peas.

Journalists and political pundits sometimes complain about the fact that food in Parliament is subsidised, so that over-paid and over-expensed MPs can eat luxurious mouth-watering food on the cheap while the hoi polloi outside the Westminster bubble has to pay through the nose for stuff that tastes like cardboard. To be honest, I don’t think such criticisms are all that fair. Food in Parliament is subsidised for everyone on the Parliamentary estate and their guests — including the journalists making such criticisms in the first place. Besides, at some tech companies and startups — most famously Google, for example — the food isn’t just subsidised, it’s free.

Fortunately, for jerk chicken lovers who do not enjoy access to the House of Commons, all is not lost. Its recipe is open source.

Trains! Trains! Trains!

I may miss the jerk chicken, but there’s one thing that I will be glad to see the back of, and that’s taking the train into London. For the past nine and a half years, I have been getting up far earlier than I’m comfortable with, spending between three and a half and four hours a day commuting, and paying up to £4,000 a year to Southern Railway for the privilege. It’s a gruelling, exhausting, stressful, expensive and wasteful regime and I wouldn’t recommend it to anybody.

By contrast, the commute to Horley from where I live is a pleasant half-hour drive, half of it through pretty Sussex villages, and half of it up the A23/M23 from Handcross to Gatwick. I love driving, and I actually find it helps me to unwind. I’m looking forward to being able to set my alarm for 7am, leave home just before 8:30, and then get back home shortly after 6pm.

It will also be significantly cheaper. I estimated that it will probably cost me around £1,000 a year in petrol to get to and from Horley. An annual season train ticket, on the other hand, costs over £1,600, while the train journey itself would take significantly longer and put annoying constraints on when I could travel.

New adventures

Change can be daunting and unnerving, and perhaps even scary, and it can also take a lot of effort. But once you step out, it can actually re-ignite passion and enthusiasm into your career. I’m looking forward to new horizons and new opportunities, and I’m once again excited about what the future holds. My last day in Parliament is 25 May, after which I will be taking a week’s break before starting at JFA on the fourth of June.

I’d particularly like to thank Paul Wilson of Arc IT Recruitment for linking me up with JFA Systems. Recruiters often get a bad reputation among developers and employers alike, but I’ve been thoroughly impressed with the professionalism and integrity that I’ve found in Paul and his team.

Finally, I’d like to thank my colleagues both past and present in the Parliamentary Digital Service for putting up with me over the past nine and a half years. They’re doing a great job playing their part in keeping the country running smoothly, and I wish them all the best for the future.

The Palace of Westminster by night, December 2008. Photo by me.

To throw or not to throw? Doing something that has already been done

The general rule for throwing exceptions (or, in Go, returning an error code) is that your function could not do what its name says that it does. This is pretty clear-cut most of the time, but there are corner cases where it’s ambiguous as to whether your function was actually successful or not.

Attempting to do something that has already been done.

Is it an error condition when your method is trying to do something that has already been done? You could argue it both ways. On the one hand, your method hasn’t been able to do what it was asked to, so it could be regarded as an error. On the other hand, the outcome of your method is what you wanted anyway, so in that sense it isn’t.

Returning success in such a condition is called idempotency. It is convenient, since it allows you to just call the method without including a superfluous and unnecessary check, and personally, it’s the option that I would prefer.

Unfortunately, there doesn’t seem to be a clear consensus on this one.

The task of creating a directory (together with any missing parents) in your filesystem is a case in point. By default, Python’s os.makedirs function throws an OSError exception, though Python 3.2 added an extra argument, exist_ok, to allow you to specify idempotent behaviour.

On the other hand, in .NET, the System.IO.Directory.CreateDirectory method takes the idempotent approach. If the directory already exists, it does not throw an exception, but merely returns a DirectoryInfo instance for the existing directory.

What was done previously was not exactly what you wanted.

Unfortunately, it isn’t always that clear cut, and things can get a bit messy. What happens, for example, if you have asked your method to create a directory with some security rules that don’t match what’s already there? Both Python and .NET (in later versions of the .NET Framework, though not in .NET Core) give you this option.

In .NET, the method simply returns without doing anything. Python 3.4.1 or later does the same when the exist_ok argument is set to True. However, this was not always the case. Python 3.2 through 3.4.0 threw an exception in this case. In theory, this should have been the correct thing to do, but unfortunately it introduced a race condition and it was not possible to fix it safely, so this was removed.

Recommendation: Always check the documentation for any methods that you call, because there is not much in the way of consistency here. But if your own function is seeking to do something that has already been done, return success by default.

Positive, negative, or error?

In my recent blog post about error handling in Go, I wrote about why I thought that they made the wrong decision by not implementing exception handling. One of the posts I linked to was this article by a Go developer called Dave Cheney.

In another article by the same author, he says that he will prove that Go’s error handling is superior. However, the example he gives is based on flawed logic. Nevertheless, it’s instructive to look at it, because there are some important things that we can learn from it.

His argument is based around this snippet of code:

package main

import "fmt"

// Positive returns true if the number is positive, false if it is negative.
func Positive(n int) bool {
    return n > -1
}

func Check(n int) {
    if Positive(n) {
        fmt.Println(n, "is positive")
    } else {
        fmt.Println(n, "is negative")
    }
}

func main() {
    Check(1)
    Check(0)
    Check(-1)
}

which, as he points out, gives this answer:

1 is positive
0 is positive
-1 is negative

which is wrong, because 0 is not positive. However, as he says, 0 is not negative either. To fix this, he proposes returning an error condition as well:

// Positive returns true if the number is positive, false if it is negative.
// The second return value indicates if the result is valid, which in the case
// of n == 0, is not valid.
func Positive(n int) (bool, bool) {
    if n == 0 {
        return false, false
    }
    return n > -1, true
}

func Check(n int) {
    pos, ok := Positive(n)
    if !ok {
        fmt.Println(n, "is neither")
        return
    }
    if pos {
        fmt.Println(n, "is positive")
    } else {
        fmt.Println(n, "is negative")
    }
}

Here’s the flaw.

What a function does should be defined by its name and any relevant established conventions.

The flaw in Dave’s logic is that he is trying to use the Positive() function for purposes for which it should not be intended. There is nothing in the function’s name that tells you that it will determine whether or not a number is negative. It only tells you that it will determine whether or not it is positive.

You can see this more clearly if we change the requirements a bit. What happens if he was asked to produce a program that, rather than telling whether a number is positive or negative, would tell whether it was prime or Fibonacci? The series of prime numbers goes 2, 3, 5, 7, 11, 13, 17, 19 … whereas the series of Fibonacci numbers goes 1, 1, 2, 3, 5, 8, 13 and so on. But should we have functions IsFibonacci() and IsPrime() that throw errors for 4, 6, 9, 10, 12, 14, 15, 16, 18, 20? Of course not!

What he needs to do instead is declare a second function, Negative():

func Positive(n int) (bool) {
    return n > 0
}

func Negative(n int) (bool) {
    return n < 0
}

func Check(n int) {
    pos := Positive(n)
    neg := Negative(n)
    if pos {
        fmt.Println(n, "is positive")
    } else if neg {
        fmt.Println(n, "is negative")
    } else {
        fmt.Println(n, "is neither")
    }
}

Neither a function called Positive() nor one called Negative() should have any preconditions whatsoever. A number — any number, zero included — is either positive or it isn’t. Zero is not positive, so you would return false. If we were dealing with floating point numbers, NaN (not a number) would not be positive, so you would return false. Strictly speaking, in dynamically typed languages, null, "Hello world", an HTTP client class, or an aardvark, are not positive either, so you would return false.

Remember that, whether you are using exceptions or error codes, an error indicates that your function could not do what its name says that it does. Making zero — or anything else — an error condition violates this rule, is outside of the scope implied by the function’s name and any well known conventions I can think of, and as such, it is counterintuitive, confusing, and wrong.

Supergiant stars are hot vacuums

You may have seen this video showing the relative sizes of different stars, and how massive some of them are:

What’s often not appreciated is that as well as being mind-bogglingly large, the largest supergiant stars are also incredibly tenuous.

Just how tenuous? Let’s take Betelgeuse as an example. There’s some uncertainty about the exact figures, but it has a mass about eleven times that of the sun, and a radius of about 900 solar radii. In other words:

Mass: 2.2×1031 kg
Radius: 6.3×1011 m
Volume: 1036 m3
Density: 2×10-5 kg/m3

On earth, a density of just 2×10-5 kg/m3 would be considered a hard vacuum. It is just one sixty thousandth of the density of the earth’s atmosphere, 1.2 kg/m3. The density of the largest known star in the video, VY Canis Majoris, is roughly similar.

Yet despite this, this gives Betelgeuse an escape velocity of about 70 km/second at its outer extremity. Betelgeuse’s enormous size is due to extreme nuclear fusion reactions in its core, where helium is converted into carbon and oxygen, and then subsequently into heavier elements, culminating in the conversion of silicon to iron. Once its supply of silicon is exhausted, nuclear fusion is no longer possible, the star collapses in on itself, and a supernova explosion results. For Betelgeuse, it is estimated that this will happen sometime in the next million years or so.