I came across Writing Solid Code by Steve Maguire (Microsoft Press, 1993) at work. My boss had a shelf full of 90’s software texts, and this one caught my eye while I was waiting for a meeting to start.
It’s fantastic, and all programmers should read it.
It’s written by an early Microsoft programmer, with experience writing for Excel. The focus of the book is C, but the ideas are applicable to almost any language. Here are some of them.
Procedures/methods/functions should do one thing well.
They should avoid special cases.
“If you pass in a pointer as the third parameter, the function will fill in the data structure it points to. But if you pass in 0 as the third parameter, the function will allocate memory and then fill in the data structure.” This type of intricate behavior allows subtle bugs or memory leaks to sneak in.
Implement complicated algorithms twice.
First, write an efficient implementation that you plan to ship with. Then write a slow implementation that you know is correct, that you will use during debugging to verify the workings of the fast one. When you’re debugging, run both implementations to check each other. Gate the slow implementation with a debug flag (DEBUG
in C or __debug__
in python). When you ship the code, turn off the slow implementation.
Make sure it is clear when a function is returning an error.
This a huge problem in C, where functions often return a pointer, and then return a special value (NULL
or 0xFFFFFFFF
) if the function failed. Callers of the function often fail to check for those error conditions, and the software fails catastrophically far from the source of error.
In a language with exceptions, you can and should make use of them to handle error conditions. See, for instance, this lovely question from the C++ FAQ. But the point remains – make sure the programmer calling your function can easily identify and handle error conditions.
Use assert
statements for behaviors that should never happen.
This helps your program fail at the earliest possible point. assert
is not just for C/C++ either. Python has an assert
statement, and so does Java. Even Haskell has one.
I’d argue that assertions are especially useful in a dynamically-typed language, like Python. If you are reading Python code for some library you want to use, you have to guess at what type the variables are, and then guess at what behaviors the code has. Assertions that explicitly limit the type of function parameters help tremendously.
You can get around this limitation of dynamic languages by running Python code in a debugger, and asking what the type of a variable is with type(<variable_name>)
. But this only tells you what type you’re seeing on this run through code, not what types are allowed.
Step through every line of code you write, and make sure it is doing what you think it is doing.
This is hard, because not all environments permit the use of a debugger. But if you can do this, you should. Little changes are sometimes the worst. They seem so obviously correct that they don’t need to be checked, and then they fail.
I found an error once in the use of C’s strcmp
, which has a terrible interface. Based on its name, strcmp
seems like it might return TRUE = 1
if two strings are equal, and FALSE = 0
if they are different. If you don’t check the C reference, this behavior seems completely plausible. But this is not how it works.
strcmp
is designed to use in alphabetizing strings. It returns a negative number if string1
comes before string2
, 0 if string1
and string2
are equal, and a positive number if string1
comes after string2
. So, if you say:
if (strcmp(string1, string2)) {
// This code executes when string1 is not the same as string2.
}
It looks like you are checking if string1
is the same as string2
. But in fact, you are checking the opposite. You will absolutely find this bug if you step through the code. But if not, who knows?
Overall
The book is sprinkled with great anecdotes. Steve Maguire is a clear and convincing writer. His sample code is lovely to read and illustrates his points succinctly. There are exercises to reinforce the ideas, and he provides answers to the exercises in the back of the book.
The book is out of print, but you can buy it used from Amazon for about $4, shipped.
I like the first edition between than Writing Solid Code, 20th Anniversary, 2nd edition. There’s not much new content in the updated edition, and it’s not as tightly edited as the first one.
The first edition reads like a dream.