A recent CodeProject article by Thorsten Bruning got me thinking about the subject of readability. Thorsten’s piece contained some rather ingenious (though somewhat extreme) ways to make code more readable for the non-programmer and is well worth a read. This article is inspired more by some of the reactions to that piece; particularly to those that take the line that we write code for our fellow developers, not for our grandmothers.
The simple truth is that all manner of people may, at some point, need to glance at our code. Whether it be a person in the Support department who doesn’t program or a fellow developer who works in a different set of languages, or, indeed, someone who needs to work on the code directly; somebody, someday is going to need to know what the code is doing.
Experience teaches us all that external documentation is rarely delivered. Far too few project managers realize the value of such things and the prevailing corporate culture dictates that it is somehow better to acquire a chunk of technical debt than to finish a job properly by leaving a nice set of notes for the unfortunate developers that have to revisit the project in the future. There is often little we can do about this beyond voicing our objections.
Internal documentation, on the other hand is entirely in our hands. As developers, we have the choice to make things as easy or as difficult for ourselves, our colleagues and our future colleagues as we see fit. I would argue that it’s actually easier to write readable code, than it is not to. The lazy coder makes far more work for himself than the diligent coder will ever have to contemplate.
Let’s have a look at some of the practices that make reading code difficult:
We’ll start with the obvious one.
At some point in our lives, we have all worked with someone whose palette of variable names covers the whole gamut from “
b_s” and “
c_s” through to “
y” and “
z”. Sometimes, to make matters worse, they will steal a code snippet from somewhere without realizing that such names as “
foo” and “
bar” are there as placeholders and copy them intact. These people shouldn’t really be allowed anywhere near a computer, of course, but if your organisation thinks that code reviews are a waste of time, you’ll wind up wasting a huge amount of time clearing up after them.
A common place to encounter the “abc” approach is in SQL queries, where you’ll often encounter the use of sequential lettering for table aliases where a simple mnemonic would suffice.
select a.UserName, c.ProductName from [User].[User] a join Request.Request b on
a.UserId = b.UserId join Product.Product c on c.ProductId = b.ProductId
Tracing back even a simple
join trail becomes a complete pain when we constantly have to ask ourselves “Which one was c, again?” This might not appear particularly different but if this was a more complicated query, the difference in reading time could amount to a great many minutes:
SELECT usr.UserName, prod.ProductName
FROM [User].[User] usr
JOIN Request.Request req ON usr.UserId = req.UserId
JOIN Product.Product prod ON prod.ProductId = req.ProductId
SQL code will never be pretty, but by using more meaningful names, using correct casing and throwing in a little whitespace, we’ve just made our query a whole lot more readable with a microscopic amount of effort.
Whilst Captain ABC is not quite as prevalent as he was back in the day, we still often find ourselves facing the obsessive abbreviator. Back in the days of manual text editors, it was a bit annoying to have to repeatedly type long, descriptive names but thanks to the wonders of Visual Studio and Intellisense, “
Employee.NationalInsuranceNumber = textboxNationalInsuranceNumber.Text;” doesn’t take too many more keystrokes than “
E.Ni = NI.Text;” and chances are you’ll know what it’s doing the next time you look at it.
Where variable names should be a simple matter of common sense and common courtesy, method naming is something that can not only help us make our code more readable but can also help us to find problems with our code.
If you dig through some bad code, at some point you’ll find a method with a spectacularly vague name such as
GetInfo() – sadly, these are all real life examples! The moment we see such a name, we know that we are heading for a huge, long, waffling method that is going to be attempting to perform far more than one action. Without any heed to concepts such as “separation of concerns” and “single responsibility”, we have a point of potentially multiple failure with no sign-posts along the way.
Methods should always be named according to exactly what they do. The way I learnt to write structured code was to read my methods and name them by whatever they did. Quite often, I would find that my names would be too long – maybe something like:
That would tell me that my code needed refactoring. The one word that we don’t want to see in a method name is “
and” - one “
and” means that we need to split our method in two, two “
ands” mean that we need to split it into three and so forth. So using this technique, I would see that my code needed to change to something like:
Not only does it separate the concerns, it’s a whole lot more readable, too.
Comments and Clever-Dickery
Meaningful naming should eliminate much of the need for in-line commentary. Excessive commentary can easily reach the point where it becomes an annoyance. I really did once work with a guy who would produce code like this:
If a comment doesn’t add anything, it becomes clutter and is ultimately self-defeating. That said, if a line of code is not instantly readable – complex lambda statements being a prime example – a comment explaining the line in simple English will be welcomed by anyone who comes into contact with your code.
All of which brings us to one of the oldest and wisest mantras of software development – “keep it simple, stupid!” One of the greatest barriers to readability is egotistic code. “Hey! Look at this! I recursively calculate it backwards then pop it all back off the stack and voila! It’s the right way round! Gee! Aren’t I clever?” Well, it’s only clever if there really isn’t a simpler way to do it. If you simply, absolutely, have to recursively calculate it backwards then pop it all back off the stack, fair enough, but provide a good explanation as to why and how you’re doing it.
Yes, sometimes, performance considerations might demand a zippy piece of pointer arithmetic where a more straightforward and readable approach might otherwise apply, but showiness for its own sake will seldom be appreciated by those that have to use your code.
We should always think of our code as belonging to the next person who has to work with it and it helps to imagine that that person is an axe-wielding maniac with a particularly short temper. Whilst making sure that Granny can read our code may not be our first and foremost objective, we should feel justifiably proud when we produce code that Granny and our less technical colleagues alike can at least catch the gist of.