Mistakes you will make in software

Almost without fail I see certain errors repeated on every single software project I come across. The projects that successfully dodge these pitfalls almost always do so because someone on the team fell into them once before and swore they wouldn’t do so again. Those of you who haven’t yet been burned by this class of error will almost certainly protest about complexity or wierd design choices in the code made by those who have.

Who are these heinous kingpins of crime in the bug ghettos of the software world? Its a work in progress, but the initial contenders are:

  • Dates and times
  • Money
  • Concatenated strings as identifiers

Those of you who’ve been beset in the past are nodding right now, those who haven’t are probably saying, “they don’t seem very complicated.”

Which is exactly why they’ll get you sooner or later. Then you’ll remember this post, and you’ll nod.

Advertisements

Feed me

It’s been kindly pointed out that my feeds and half my category links are broken and have been for a while. Probably nobody is left who still actually uses a browser to read blogs, but, as this dovetails rather precisely with my assumptions about readership size; and faffing with moveable type templates rates somewhat lower than not, it may take a while before it all gets sorted. Apologies to anyone who’s still committed enough to make the effort, I’ll try and get round to sorting it.

Tiny Types

There’s a pattern I’ve used with great success a couple of times now that tends to provoke strong reactions in developers when they first see it. I’ve had comments along the lines of “that’s horrible!”, “ugh” and “that’s way too much work”. The pattern is this: the encapsulation of simple built-in types within domain specific classes. Sounds simple and it is.

Lets take a concrete example:

public class Customer {
private final String firstName;
private final String familyName;
private final int ageInYears;
private final int heightInCentimetres;

public Customer(String firstName, String familyName, int ageInYears, int heightInCentimetres) {
this.firstName = firstName;
this.familyName = familyName;
this.ageInYears = ageInYears;
this.heightInCentimetres = heightInCentimetres;
}
}

Fairly standard stuff. But note the constructor signature: string, string, int, int. Not really very expressive and exceedingly easy to get the parameters out of order. But who would get someone’s first and last names mixed up? Ask any Chinese person how often that happens. They place their family name before their given name. Also, strings and integers are not usually domain concepts unless you are writing a compiler. Someone’s first name is not interchangeable with their last name the way two strings are. So how about this:

public class Customer {
private final FirstName firstName;
private final FamilyName familyName;
private final Age age;
private final Height height;

public Customer(FirstName firstName, FamilyName familyName, Age age, Height height) {
this.familyName = familyName;
this.firstName = firstName;
this.age = age;
this.height = height;
}
}

It is at this point that most developers recoil. No way do I have time to add an entire class just to wrap a string! Or two entire classes in this case! Actually, it’s four new classes. All of which I wrote while writing this post. There is a reasonable amount of boilerplate. Including toString, equals, hashCode and a getter makes for about 40 lines per tiny type, almost all of which can be condensed into an IDEA template. And most systems have a finite number of domain concepts so the rate of adding these tiny types isn’t very high and drops off fairly quickly.

But why do this? I consider it playing to the strengths of a statically typed language. Java will never be as Ruby as Ruby, but it can be much more Java than Ruby ever will. All sorts of useful things start to happen when the library types and primitives have been banished from your api. Now the compiler can spot transposition errors. Equals and hashCode can be implemented with domain specific semantics. It’s much harder to accidentally pass dollars into a method that was expecting pounds sterling (but actually took a double so it could have been anything). Readability is greatly improved. Automated refactoring, code completion and code navigation all gain a new level of power. ‘Find usages’ on the FirstName class produces far more useful results than doing it on the String class.

You probably still don’t fully believe me if you haven’t tried it, but this is one of those times where cognitive dissonance has got it wrong. It really is an exceedingly useful approach.