There are at once too many and too few books on software design—particularly, software design in the small. By “in the small,” I mean design at the level of implementation and coding, rather than at the architectural level. There are numerous books written by consultants that offer advice primarily designed to inveigle the reader in the author’s preferred approach. But truly good books in this area are rare. Perhaps the most recent is Growing Object-Oriented Software, Guided by Tests, by Steve Freeman and Nat Pryce. It dates from 2010. Earlier, in 2007, there was Kent Beck’s woefully underappreciated Implementation Patterns.
Comes now this thin, inexpensive volume from John Ousterhout, which addresses many of the class-level coding and design issues that confront us daily. Ousterhout is the inventor of the first widely adopted scripting language, Tcl, and the founder of Electric Cloud, a company that specializes in continuous delivery tools for sites that work on huge projects (in millions of lines of code). In between, he’s been a professor of computer science at Stanford University and the University of California, Berkeley. It’s safe to say he understands design, especially of large projects.
This book is a series of key principles aimed at reducing complexity and grounded in unwavering pragmatism. There is no overarching philosophy that Ousterhout is trying to convince you of (despite the book’s title). Instead, he treats topics such as how to reduce innate complexity, how to code modules to contain and hide the complexity, how to think about abstractions when coding, and so on.
A pair of chapters, comprising some 25 pages, is devoted to comments—which might seem a lengthy diversion until you realize that they are a cornerstone to the other practices. Ousterhout recommends that the first thing you do when creating a class is to write comments, which he segregates into two types: high-level and low-level. High-level comments address what the class is about and its relationship to other classes. Reading these comments, you should not need to read anything else unless you need to know the implementation. The low-level comments are the ones that you sprinkle throughout the implementation to illuminate the why and how—only if it is not clear from the code itself. Comments, he points out, should lower the cognitive load and make code clearer. He then presents handy, pragmatic conventions for commenting.
He also addresses module cohesion, code repetition, error handling, testing, and even performance tuning—always with an eye toward his central goal: reducing complexity, both intrinsic and incidental. At 170 pages, this book is an easy read and brimming with original ideas. Most code examples are in Java. Highly recommended.