Recommended Software Books

Robert P. Goddard

29 May 2002

This is my personal compendium of the most valuable software engineering books. It includes only books that I have read (or read most of anyway). I'm sure there are other good books out there, but I will recommend only what I know.

TOC for this page



Software Project Management

Software Project Survival Guide: How to be sure your first important project isn't your last

by Steve McConnell. Microsoft Press, 1998. ISBN 1-57231-621-7.

I bought this book some time ago, but I didn't get around to reading it until recently, after Raffaella Bano recommended it as the first book one should read on software project management. It is aimed at "medium-size" projects (RFPK qualifies), not huge ones, so McConnell recommends a lot less "process" and paperwork than some others (e.g. "The Unified Software Development Process"). I found McConnell's recommendations to be reasonable and practical. Many of them are things we are already doing, and most of the rest are things that I think would help a lot to keep us out of trouble.

The companion Web site, http://www.construx.com/survivalguide/, provides checklists, forms, and other resources that can be copied and adapted for each project. These look quite useful.

Peopleware: Productive Projects and Teams

by Tom DeMarco and Timothy Lister. Dorset House, 1987, ISBN 0-932633-05-6.

Aging but still valuable. This book puts the focus where it always belongs, on the people doing the work.

The Mythical Man-Month

by Frederick P. Grooks, Jr. Addison-Wesley, 1975. ISBN 0-201-00650-2.

This ancient chestnut marked the beginning of the end of the old "waterall model".


Object Oriented Software Design

Fundamentals of Object-Oriented Design in UML

by Meilir Page-Jones. Addison-Wesley, 2000. ISBN 0-201-69946-X.

All software designers and programmers should read this one. The Introduction is the best summary I have seen of what "object oriented" really means and what it is for. Part II (most of the first half of the book) introduces the UML notation. It can be skimmed quickly if you already know UML. The meat is in Part III, the last half of the book. What is OOD trying to do? How can you tell the difference between a good design and a bad one? What are some of the ways you can go wrong, and what should you do instead, and why? How do you go about the process of software design?

This is not a C++ book. Most of the hardest parts of C++, like memory management and templates, are skimmed over or left out in favor of an intense focus on the concepts that are common to all OO languages. These are the things we should be thinking about first, even in C++.

UML Distilled: Applying the Standard Object Modeling Language

by Martin Fowler with Kendall Scott. Addison-Wesley, 1997. ISBN 0-201-32563-2.

Forget the three "official" UML books by the Three Amigos (Booch, Jacobson, Rumbaugh permuted: UML User Guide, UML Reference Manual, and The Unified Software Development Process). This one has what you need in a lot fewer pages, better written. And it outlines the incremental, iterative approach to software construction, and even touches on refactoring.

This coverage of UML is more complete than the first half of Page-Jones (above) because Fowler is aiming at all of the uses of UML in all phases of the software life cycle, whereas Page-Jones focuses on design. Nevertheless, it is a small book. That's good.

Design Patterns: Elements of Reusable Object-Oriented Software

by Erich Gamma, Richare Helm, Ralph Johnson, and John Vlissides. Addison-Wesley, 1994. ISBN 0-201-63361-2.

This is the "Gang of Four" book, known as "GoF", one of the most widely quoted books in the OO literature. It gives a list of common "design patterns" with which groups of objects can interact. Each pattern is described with a common outline: Intent, Motivation, Applicability, Structure, Participants, Collaborations, Consequences, Implementation, Sample Code, Known Uses, and Related Patterns. The GoF pattern names have entered the common OO vocabulary. If you don't know about Abstract Factory or Observer or Template Method or Singleton or Visitor, you haven't been paying attention. Read it.

Refactoring: Improving the Design of Existing Code

by Martin Fowler, with contributions by Kent Beck, John Brant, William Opdyke, and Don Roberts. Addison-Wesley, 1999. ISBN 0-201-48567-2.

Most programmers are reluctant to touch existing code that "more or less works" for fear of irretrievably breaking it. So they add functionality in ways that keep working around the existing flaws, thereby making the flaws more firmly entrenched and making future modifications even harder -- et cetera, until the structure topples. Don't start down that path. Instead, every time you run into an existing design flaw while you are adding to or modifying code, step back, think a bit, put on your refactoring hat, fix it, and test it. Then take off your refactoring hat, put on your modification hat, and put in the new code that was your original objective.

This book gives specific guidelines about when, why, and how to accomplish various kinds of refactoring. The whole approach leans heavily on creating and using a particular kind of test that can be run often -- sometimes many times per day -- producing a simple "yes or no" answer. The book is worth reading just for the chapters on testing. The chapter on "bad smells in code" is another high point. It's all very much worth reading.


C++ Programming

C++ Primer, Third Edition

by Stanley B. Lippman and Josée Lajoie. Addison-Wesley, 2000. ISBN 0-201-82470-1.

This is "a comprehensive introduction to the International Standard on C++. It is a primer in the sense that it provides a consciously tutorial approach to C++. (It is not a primer in the sense of providing a simplistic or "gentle" description of the language.) ... The book is intended as a first book on C++; it is not intended as a first book on programming!" (from the Preface)

I especially like the fact that the facilities of the Standard Library are introduced early, alongside their C counterparts. For example, both C character strings and the std::string class, and both C-style built-in arrays and the std::vector class, are compared and contrasted at the beginning. Examples use the Library by preference, as programmers should do. A whirlwind tour of the entire language and library, in the first two chapters, gives you enough of an overview to allow the examples in the rest of the book to be "good" C++, not toy stuff you will want to throw away after you learn a better way. After that introduction, the book starts over with a thorough discussion of each feature, in a more traditional order from simple to complex. Numerous detailed examples and exercises help make it a good learning tool, suitable for classroom or individual use.

On the negative side, this book's coverage of the standard library is far from complete. In particular, this isn't the right book if your primary interest is use of C++ for numerical (scientific) programming. The std::complex template class gets a very brief, incomplete treatment. Most of the library components of primary interest to numerical programming are not mentioned at all: These include the std::numeric_limits and std::valarray template classes, and even the standard mathematical functions (like sin() and atan()). Important non-numeric topics that are omitted include template template parameters, locales, the streambuf level of the iostream library, iterator traits, character traits, wide characters, and the template nature of the iostream and string libraries. Some people may want to start with this book, but it would be a serious mistake to stop here.

The C++ Programming Language, Special Edition (or Third Edition)

by Bjarne Stroustrup. Addison-Wesley, 2000. ISBN 0-201-70073-5. Third edition: 1997.

Note on editions: The Special Edition is a very recent hardcover version that is essentially the same as the Third Edition (1997) except for a few corrections, minor updates to track the final standard, and two new appendices on locales and standard library exception safety. The new appendices are also available at http://www.research.att.com/~bs/. I bought the hardcover version because I have used my 1997 softcover book so much that the pages were falling out. The first two editions (1985 and 1991) are pretty thoroughly out of date. The third and special editions describe the final ISO/ANSI C++ standard, which is a significantly different language from that described in the first two.

Every C++ programmer must have this book. Until the new "Annotated Reference Manual" comes out (should be soon), this book is the definitive authority on what's in C++. Even after the new ARM comes out, it will be of limited use to most C++ users because the Standard is written mostly for compiler writers, which makes it pretty obtuse for the rest of us. This book will remain the reference of choice for most purposes.

But: It's not just a reference book. It tells you why each feature exists and how it ought to be used, with examples. Stroustrup invented C++, so he knows. And he writes clearly and well. So, don't just leave it on your bookshelf to look stuff up. Read it. Take it to lunch. Take it to the head. Take it to bed. Take it on vacation. Whatever. Start with the introductory material, study the last three chapters on design, skip around in the rest if you want, but sooner or later every C++ programmer should read all of this book.

Programming Languages -- C++

International Standard ISO/IEC 14882, First edition 1998-09-01. By the X3 Secretariat, X3J16-14882. Information Technology Council (NSITC). Washington, DC, USA. Available for purchase through http://webstore.ansi.org.

If you really want to know the definition of Standard C++, there is no substitute for going to the source. I usually look in Stroustrup first, but this is the final arbiter. It's not expensive. Pull out your credit card, download the PDF file, and keep it handy for those occasions when nothing less will do.

Effective C++, Second Edition: 50 Specific Ways to Improve Your Programs and Designs

by Scott Meyers. Addison-Wesley, 1998. ISBN 0-201-92488-9.

More Effective C++: 35 New Ways to Improve Your Programs and Designs

by Scott Meyers. Addison-Wesley, 1996. ISBN 0-201-63371-X.

Note: There is also a newer CD-ROM edition that includes both books, updated somewhat, plus some extra examples and other stuff. I don't have it, but I have heard it is good too.

These are the second and third C++ books that every C++ programmer should know by heart. They consist of concrete advice, with reasons and examples, in easy-to-digest chunks. Meyers is one of the best writers in the field. He emphasizes his points with humor. Even the Index is entertaining (where else will you find references to Socrates, Twilight Zone, and "French, gratuitous use of"?). Read them in order or skip around, but read them.

Exceptional C++: 47 Engineering Puzzles, Programming Problems, and Solutions

by Herb Sutter. Addison-Wesley, 2000. ISBN 0-201-61562-2.

This entertaining, mind-stretching puzzle book grew out of the "Guru of the Week" series on the Internet discussion group comp.lang.c++.moderated. If you think you know C++, this will open your eyes. A big section on exception safety is especially valuable.

More Exceptional C++: 40 New Engineering Puzzles, Programming Problems, and Solutions

by Herb Sutter. Addison-Wesley, 2002. ISBN 0-201-70434-X.

This one is not quite as compelling as its predecessor, but it's still worth reading to hone your skills. Advice for both of these books: Each section starts with a set of questions. Before you read on to the solutions, spend at least several minutes thinking about the questions, and consider working out or outlining your own solution. Sutter's version is almost sure to stretch your understanding of OO principles and C++ specifics.

Large-Scale C++ Software Design

by John Lakos. Addison-Wesley, 1996. ISBN 0-201-63362-0.

Most software design books cover "logical" design at the scale of functions, classes, and stand-alone applications. This one covers some of the same territory, with an emphasis on the factors that get more important as the scale of the software increases. Then it extends those ideas with concepts like packages, libraries, components, and systems. And it goes beyond logical design to "physical" design: How should one organize the directories, header files, source files, library files, executables, documents, data, and other products that make up a big C++ program, and why? The key concept is controlling logical and physical dependency among components at each scale. At the scale of my projects (SST, SPK, and DML), 10k to 100k lines of code, we can afford to pick and choose among Lakos's recommendations, but it's good to know where the boundaries are and what lies near and beyond them.

The Design and Evolution of C++

by Bjarne Stroustrup. Addison-Wesley, 1994. ISBN 0-201-54330-3.

If you ever wondered why C++ does things as it does, or how it got that way, this is the book for you, directly from the inventor of the language. The high point is Chapter 4, which explicitly lays out the fundamental aims and design rules of the language. It is preceded by some historical stuff to give context, and followed by an explanation of how and why each feature of the language and library supports those aims and rules. The only major piece that is missing is the Standard Template Library, which was just getting started at Hewlett-Packard in 1994.

Efficient C++: Performance Programming Techniques

by Dov Bulka and David Mayhew. Addison-Wesley, 2000. ISBN 0-201-37950-3.

C++ is an appropriate language for performance-critical applications. This book tells you how to avoid the common pitfalls that have led to the widespread opinion that C++ is slow. The TANSTAAFL principle ("There ain't no such thing as a free lunch" -- Robert A. Heinlein) still applies, but with C++ you don't have to pay for high-level object-oriented features unless you use them. And you can use them without unreasonable penalty if you use them wisely.

The book covers the main C++ performance issues: constructors and destructors, virtual functions, temporaries, memory management, inlining, the Standard Template Library, reference counting, and the important distinctions between single-threaded and multi-threaded code (single-threaded optimizations are often multi-threaded pessimizations). It distinguishes carefully between coding optimizations and design optimizations, giving important examples of each. It goes into system architecture issues like cache effects, and the special considerations of programming for shared-memory multi-processor systems.

My main disappointment was that insufficient emphasis was placed on the importance of measurement (especially profiling) as a guide for deciding where to optimize and where not to. Also, the specific issues of importance to numerical programming were omitted, and advanced optimization techniques like expression templates went unmentioned. Nevertheless, if you care about C++ program speed, you need to know what's in this book.

C++ Network Programming, Volume 1: Mastering Complexity with ACE and Patterns

by Douglas C. Schmidt and Stephen D. Huston. Addison-Wesley, 2002. ISBN 0-201-60464-7.

Software requiring communication between processes or computers is notoriously un-portable, low-level, difficult to program, and error-prone. The Adaptive Communication Environment (ACE) is a freely available set of object-oriented software components (middleware) designed to alleviate all of those problems. This volume describes the bottom few layers of ACE, which provides a portable platform supporting sockets, events, processes, threads, and synchronization tools such as mutexes and semaphores. It clearly describes the necessary communication tasks, the existing system-level tools to address them, the weaknesses of those tools, the design dimensions available for fixing them, and the logic behind the design of the ACE middleware. This general material is accompanied by specific (but not detailed) descriptions of the individual ACE components. The emphasis throughout is on why ACE does things the way it does, with frequent reference to the pattern literature (including Gamma et al., reviewed above). The book is valuable as an introduction to the issues inherent in network programming, as an introduction to ACE for potential users, and as a set of case studies demonstrating good object oriented design.

Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library

by Scott Meyers. Addison-Wesley, 2001. ISBN 0-201-74962-9.

To be reviewed soon.

Standard C++ IOStreams and Locales: Advanced Programmer's Guide and Reference

by Angelika Langer and Klaus Kreft. Addison-Wesley, 1999. ISBN 0-201-18395-1.

To be reviewed soon.


C++ Template Metaprogramming

Generic Programming and the STL: Using and Extending the C++ Standard Template Library

by Matthew H. Austern. Addison-Wesley, 1998. ISBN 0-201-30956-4.

C++ supports several fundamentally different paradigms. The one most often associated with C++ is object-oriented programming. This book is about another one: generic programming, which centers around the effective use of templates. The Standard Template Library, or STL, was invented at Hewlett-Packard Laboratories by Alexander Stepanov and Meng Lee and developed further at Silicon Graphics (by Austern among others). It is now part of the standard C++ library. STL supports generic programming, but there is more to generic programming than the STL (just as there is more to object oriented programming than standard library classes).

Stroustrup's chapters on the Standard C++ Library are adequate if you just want to use the STL as provided. But Stroustrup covers it lightly, and leaves some important concepts unexplored. If you really want to understand generic programming in general, and STL in particular, thoroughly enough to design and write your own generic components, you will need to take the next step and read Austern. And, as a bonus, you get a well-organized, complete, very usable STL reference manual too.

Modern C++ Design

by Andrei Alexandrescu. Addison-Wesley, 2001. ISBN 0-201-70431-5.

After you have mastered basic non-template C++ to the level of Scott Meyers's Effective C++ books (reviewed above), and understand templates well enough to use the STL effectively (Austern's book, reviewed above, will help), the next big step is this book. It starts out with a careful treatise on policy-based class design, a set of principles supporting multi-dimensional variation in properties of a class. (For example, one "counted pointer" can differ from another in how it stores the reference count, whether and how it supports multi-threaded programs, what happens when it is copied, and so forth.) Then it introduces a mind-stretching set of C++ techniques that go beyond generic programming into template metaprogramming: techniques for persuading the template-evaluation parts of the C++ compiler to do amazing feats of code generation at compile time.

The second part of the book convincingly demonstrates the utility of these principles and techniques by describing the design and construction of Loki, which is a freely available library of powerful, useful C++ components that (in my opinion) are a sure bet for inclusion in the next C++ standard. Components of Loki include a fast, flexible small-object allocator, and flexible, efficient templated classes supporting familiar design patterns (see Gamma et al. reviewed above):

ending with an appendix describing a minimalist multithreading library.

At one level, this is a serious book for serious advanced C++ programmers, worthy of careful study when you feel ready for it. At another level, it's an introduction to a great set of tools that any C++ programmer can use effectively. This is important stuff, and it will get more important in the coming years as the ideas mature. Read it and get in on the ground floor.

Generative Programming: Methods, Tools, and Applications

by Krzysztof Czarnecki and Ulrich W. Eisenecker. Addison-Wesley, 2000. ISBN 0-201-30977-7.

This is an important, ground-breaking, revolutionary, scholarly work. It started out as Czarnecki's Ph.D. dissertation. It's the source for many of the ideas that Alexandrescu put to work in the book reviewed above, plus a lot more and deeper, and not restricted to C++. The people who write the advanced books for programmers need to read this one.