This is an HTML rendering of a working paper draft that led to a publication. The publication should always be cited in preference to this draft using the following reference:
The Pragmatic Programmer: From Journeyman to Master by Andrew Hunt and David Thomas, Addison Wesley, Reading, Mass., 2000, 0-201-61622-X, 321 pp., US $34.95.
Early in my programming career, I was lucky to come across Brian Kernighan and P.J. Plauger's Elements of Programming Style (McGraw-Hill, 1978) and Jon Louis Bentley's Programming Pearls (Addison Wesley, 1985). These books deeply influenced me. Since 1988, when the last volume of Programming Pearls was published, no book has matched the insight and empathy to programming of those works. Although Elements of Programming Style is a classic, its RATFOR (rational Fortran) examples made me hesitant to recommend it to colleagues and students.
Fortunately, the last two years have blessed us with a new edition of Programming Pearls, Kernighan and Rob Pike's the Practice of Programming (Addison Wesley, 1999), and now Andrew Hunt and David Thomas's The Pragmatic Programmer (www.pragmaticprogrammer.com). The progress of technology has brought with it new tools and approaches. Scripting languages, client-server computing, graphical user interfaces, integrated development environments, object-orientation, Web applications, and Internet time all provide new opportunities and challenges for today's programmer. The Pragmatic Programmer addresses these issues and more, making the authors' experience accessible to all programmers.
The authors typically condense their discussion of many topics in the form of a memorable one-line tip. These span from the functional, "learn a single editor well," to the practical, "coding ain't done till all tests run," to the deep, "abstractions live longer than details."
Hunt and Thomas have a talent for making concepts accessible and for motivating readers by using inspiring analogies. Revision control systems are fittingly compared to an "undo key" that spans an entire project's lifetime; all programming artifacts, not just source code, should therefore be placed under revision control.
On the subject of refactoring-which both in academia and industry has not received the attention it deserves-Hunt and Thomas assert that software construction shares more common traits with gardening than with building construction-a recurrent analogy in software engineering circles. Plants can thrive, but they need pruning. Minor adjustments can make the garden more aesthetically pleasing, but activities such as monitoring the garden's health, moving plants around, and fertilizing never stop.
Finally, when discussing specifications, Hunt and Thomas ask readers to write a specification for tying shoelaces, the morale being that some things are easier done than specified.
Although many excellent books cover software design, most of them, written by the very people behind a specific methodology, are necessarily narrow-focused. Refreshingly, we can turn to Hunt and Thomas for a broad and accessible anthology of approaches that work. For example, they suggest when to structure an application around services, offer details on when and how to implement a model-view-controller structure (mind you, not just for graphical presentation), and explain how to use blackboard techniques.
By now, we all know the problems of the rigid waterfall model development processes; it is encouraging to see that the authors provide concrete advice on how to incrementally develop software. The tracer code approach they advocate is based on the development of architecturally complete-if not fully functional-code for demonstrating and concept-testing a software system. (The approach gets its name from another analogy: the tracer bullets used to identify a weapon's firing direction). This development mode-also advocated in a slightly different form by the Extreme Programming approach ("implement the most important features first")-complements rapid prototyping as a way to obtain early feedback during development.
To keep the volume of the book manageable, many concepts and ideas are presented in a cursory style and some examples are rather contrived. I got the impression that the authors have enough experience to fill two books-one for each of them. Instead, as the next best thing, they provide references to practical books and pointers to free tools and documentation available on the Web. A selective bibliography complements the material offered. Although the books I mentioned in the first paragraph and Andrew Koenig's C Traps and Pitfalls (Addison Wesley, 1988) are unfortunately missing, the annotated bibliography can serve as a shopping list for populating a budding programmer's bookshelf.
I often found myself nodding and smiling while reading the book; the authors have successfully mined nuggets from the current programming practice field and made them available in an accessible and enjoyable form. I will certainly recommend this book to people whose code I will have to read or use.
Diomidis Spinellis is an assistant professor in the Department of Information and Communication Systems at the University of the Aegean. Contact him at firstname.lastname@example.org.