- Subtitle:
-
“Microsoft's Techniques for Developing
Bug-Free C Programs”
- Author:
- Steve Maguire
- Publisher:
- Microsoft Press
- First published:
- 1993
- ISBN:
- 1-55615-551-4
I don't normally buy books like this. In fact, I didn't buy this one
either: I was given it by a neighbour (whom I don't
think has read any of my code...) and thought it
might be worth a skim. The writing is relatively conversational; chunks of
it wouldn't feel out of place as posts to a technical blog. The book is a
series of tips, presented with supposedly catchy titles such as
“Inconsistency, the Gremlin of Code” (which I liked) and
“Watch your Language” (which seems like a poor effort to me)
and a couple of pages of plausible, but invented, motivating examples of
ways in which trouble can strike, and the solution. These tips are grouped
into eight categories: A Hypothetical Compiler discusses
using warnings from the compiler, lint and similar tools to
find potential bugs mechanically; Risky Business is
about surprising aspects of the C language and differences between CPU
architectures; and so on.
Scattered through the book are anecdotes about Steve Maguire's
time working on early products (mainly Excel) for the Apple Macintosh
at Microsoft, which provide insight into the company's development
practices, and (more interestingly) how startlingly unwise they used to be.
(Apparently, at one point standard practice was to leave fixing any and all
bugs until the product was feature-complete. Uhm...)
Many of the suggestions made are fairly C-specific, as the subtitle
suggests. Aside from advice directly relating to syntactic issues, many
of the memory corruption-related bugs discussed cannot occur in safer
languages, and higher-level tongues solve a number of portability issues
for you. But other tips are more general: for instance, making functions do
one well-documented job well rather than turning them into Swiss Army
chainsaws is good practice in any language (and is one of the key tenets of UNIX-like systems). The advice given is sound,
although sometimes seems hardly worth stating. Sure, code like
(x ? (y ? bacon : ham) : salami)("let's talk about
pork")
is unreadable and unidiomatic, and would be better written as
if (x) {
if (y) {
bacon(message);
} // etc.
...but no-one would actually write the former in C, would they? (Of course,
functional languages are another matter!) There are also
some omissions, one of which is Maguire's apparent failure to mention
mandatory code review. I first encountered this practice when working on
Telepathy-related projects, where all patches are reviewed by at least one
other developer before being merged, and it seems to help avoid even
relatively subtle bugs creeping in — more so, I claim, than would
stepping through every branch of every function you write in a debugger,
which is the subject of an entire chapter of Writing Solid Code.
It's a pretty solid book, but I wouldn't buy it. Too much of the advice is
either obvious or irrelevant: I'm never going to write my own replacement
malloc library, nor my own assert() macro. The
space wasted in binaries by debug strings may have mattered in
1993, but it's negligible even on mobile devices fourteen years later. (Oh,
and no-one's ever going to convince me that encoding
type information in variable names is anything but
redundant.1) But if you write C, and find yourself with a spare
half hour and a copy from someone else's bookshelf, it's definitely worth flicking
through.
1 see also Joel Spolsky's article on
how Hungarian notation
went wrong.