Recommended Reading

Greg Wilson gvwilson@ddj.com

I've reviewed over a hundred and fifty books for Doctor Dobb's Journal and other magazines in the last twelve years. At first, I thought I was just telling people what they should or shouldn't read. After a while, though, I realized that I was actually using my reviews to think aloud about what really matters in computing: how to turn today's chaotic, hit-and-miss development practices into a craft as reliable as carpentry, and perhaps one day into real engineering.

All of the books I describe in this article point us in that direction. The first four sections list my favorites in several areas, while the fifth section covers some very good books that are well worth reading, but for one reason or another didn't quite satisfy me. None of the classics from http://www.ercb.com/feature/feature.0013.html are on this list; you won't find Knuth's Art of Programming, or Brooks's Mythical Man-Month. Instead, I have concentrated on books that actually changed the way I program, or the way I think about programming.

In the last section, I describe half a dozen books that I would really like to review, but that no-one seems to have written yet. As I said four years ago in "Not on the Shelves" (http://www.ercb.com/feature/feature.0012.html), these reviews of non-existent books are my attempt to point out gaps in the programming literature, and indirectly, gaps in most programmers' education (including my own). If by chance you are already writing one of these, please let me know, so that I can review it for real when it comes out.

Essentials

Andrew Hunt and David Thomas: The Pragmatic Programmer
Every time we hire a new junior programmer, I give them this book to read. Every time, they come back and say, "I wish I'd had a course about this stuff at college." The Pragmatic Programmer is about those things that make up the difference between typing in code that compiles, and writing software that reliably does what it's supposed to. Topics range from gathering requirements through design, to the mechanics of coding, testing, and delivering a finished product. The second section, for example, covers "The Evils of Duplication", "Orthogonality", "Reversibility", "Tracer Bullets", "Prototypes and Post-It Notes", and "Domain Languages", and illuminates each with plenty of examples and short exercises. If you only read one book from this list, do your customers a favor, and make it this one.

Jeff Johnson: GUI Bloopers
Most books on GUI design are long on well-meaning aesthetic principles, but short on examples of what it means to put those principles into practice. In contrast, GUI Bloopers presents case study after case study: what's wrong with this dialog? What should its creators have done instead. And, most importantly, why? The net effect is to teach all of the same principles that other books try to, but in a grounded, understandable way.

Robert Sedgewick: Algorithms in C (5 volumes)
Far too many programmers still think and code as if resizeable vectors and string-to-pointer hash tables were the only data structures ever invented. These books are a guide to all the other conceptual tools that working programmers ought to have at their fingertips, from sorting and searching algorithms to different kinds of trees and graphs. The analysis isn't as deep as that in Knuth's monumental Art of Programming, but that makes the book far more accessible. And while the author's use of C may seem old-fashioned in an age of Java and C#, it does ensure that nothing magical is hidden inside an overloaded operator or virtual method call.

Bill Zoellick: CyberRegs: A Business Guide to Web Property, Privacy, and Patents
Everyone working on the Internet these days (which means just about everyone) has to wrestle with the complexities of electronic privacy and property rights. In this book, Zoellick looks at how pre-existing legal machinery, such as copyrights, patents, and the very idea of "jurisdiction", are evolving to meet new demands. He starts with a clear-headed analysis of the Napster case, pointing out that US copyright law was originally practical, rather than moral, in intent. Zoellick goes on to weave history, ideas, and analysis together in a fascinating, but sometimes scary, look at what we're doing, and at how dangerously close we have already come to stifling development with a few badly-written laws.

Languages

Elizabeth Castro: XML for the World Wide Web
Like other books in Peachpit's Visual Quickstart series, Castro's XML for the World Wide Web is beautifully designed, and easy to read without ever being condescending. Its 16 chapters and 4 appendices are organized into 1- and 2-page explanations of particular topics, from writing non-empty elements to namespaces, schemas, and XML transformation. Throughout, Castro strikes a perfect balance between "what", "why", and "how", and provides a surprising amount of detail without ever overwhelming the reader.

Nigel Chapman: Perl: The Programmer's Companion
Chapman's introduction to Perl has three strengths: it is clearly written, it talks as frankly about Perl's many weaknesses as it does about the language's strengths, and it eschews the cute in-jokes that plague many other Perl books. As a bonus, the author's emphasis on programming idioms, rather than language features, means that almost every page teaches you how to do something useful. With this as an introduction, you will be more than ready for the O'Reilly reference books, or for my two other favorites, David Cross's Data Munging with Perl and Lincoln Stein's Network Programming with Perl.

Mark Lutz and David Ascher: Learning Python
This is not only the best introduction to Python on the market, it is one of the best introductions to any programming language that I have ever read. Lutz and Ascher cover the entire core of the language, and enough of its advanced features and libraries to give readers a feeling for just how powerful Python is. In keeping with the spirit of the language itself, their writing is clear, their explanations lucid, and their examples well chosen.

Scott Meyers: Effective C++
I still haven't found an introduction to C++ that I like, but I think that is more of a reflection on the complexity of the language than a failing of the many good authors who have tried to write one. Meyers' Effective C++, however, ought to be on every C++ programmer's shelf, and his rules ought to be burned into every programmer's ROM, as it describe how C++ ought, and ought not, to be used. His rules range from the highly-specific ("Item 6: Use delete on pointer members in destructors") to the broadly general ("Item 18: strive for class interfaces that are complete and minimal"), but each one is backed up by both explanation and examples. The highest praise for this book is its sequels and imitators, from Meyers' own More Effective C++ and Effective STL to Effective Java, COM, and Perl, all of which are well worth reading.

As a footnote to this section, I still haven't found an introduction to Java for people who already known how to program that I really like. If you have a favorite, I'd enjoy hearing about it.

Advanced Topics

Martin Fowler et al: Refactoring: Improving the Design of Existing Code
Like architects, most programmers spend most of their time renovating, rather than creating something completely new on a blank sheet of paper. This book presents and analyzes patterns that come up again and again when programs are being reorganized. Some of these are well-known, such as placing common code in a utility method. Others, such as replacing temporary objects with queries, or replacing constructors with factory methods, are subtler, but no less important. Each entry includes a section on motivation, the mechanics of actually carrying out the transformation, and an example in Java.

Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides: Design Patterns
This book became a classic the moment it was published, and its reputation and influence have only grown since then. Its core catalogs and analyzes two dozen patterns that our experience shows us make the difference between a "steaming pile of code" and a robust, flexible product. Some of their terms, like "singleton" and "proxy", have become part of our working vocabulary, while dozens of other books have explored patterns in business processes, database design, concurrent systems, and refactoring (see the previous review). That said, the book is hard going, even for experienced programmers, and I think most readers would be better served these days if the examples in C++ were mirrored in Java or Python, rather than in Smalltalk.

Richard Jones and Rafael Lins: Garbage Collection
Garbage collection itself is almost as old as high-level programming languages---the first papers on it were published in 1960---but it took Java to bring it into the average programmer's life. Those who really care about the subject will find this book invaluable. After some introductory material, Jones and Lins present the three classical algorithms: reference counting, mark-sweep, and copying. Chapters three to twelve then present successively more intricate extensions to these algorithms, from pointer reversal to generational garbage collection. Each chapter ends with a section titled "Issues to consider", which sums up and analyzes the points made in the preceding pages. Together, these sections transform the book from "just" a thorough survey into the sort of engineering manual that computing so rarely produces.

John R. Levine: Linkers and Loaders
Parsers and code generators are a standard part of the undergraduate computer science curriculum, but for some reason, the other half of producing a working program---linking compiled modules together, and then loading those modules to create a runnable program---is not. Levine's excellent survey of these topics looks at the solutions used on the IBM 370, Solaris, Microsoft Windows, and several other platforms. Along the way, he examines the pros and cons of different object file formats, relocation, and the way names are mangled in C++. It may all seem fairly arcane, but if I'd had this book twelve months ago, and had understood that Visual C++ resolved some names earlier than the Unix compilers I had grown up with, I wouldn't have had to spend three days reading assembly code.

Derek M. Powazek: Design for Commmunity
This book isn't about web logging, streaming video, or managing mailing lists. Instead, it's about how to structure web sites so that they will foster on-line communities. The writing is personal without being sappy or overbearing, and the author draws upon a wealth of personal experience to explain why you sometimes don't want to make it easy for people to post comments, or how best to deal with abusive posters. There's a lot of no-nonsense analysis of the cost of interactivity, and interviews with the creators of some of the web's most successful community sites.

Doug Rosenberg and Kendall Scott: Use Case Driven Object Modeling with UML
UML's kitchen-sink approach to object-oriented analysis and design makes it hard to navigate, but still leaves an uncomfortably wide gulf between the analysis ("what") and design ("how") phases of a project. The principal value of this book is that it tackles both of these issues head-on, while showing when and how the different elements of UML should be used. In just eight chapters, Rosenberg and Scott present a slimmed-down core of UML, organized around a four-stage design process. Each stage has clearly defined steps, and concrete milestones that specify what ought to be produced (that is, how to tell when you're finished). The companion workbook, Applying Use Case Driven Object Modeling with UML, presents a series of "spot the error" exercises that further clarify this complex topic.

Allan M. Stavely: Toward Zero-Defect Programming
This book is a slim, readable description of the Cleanroom development practices first used at IBM. Unlike most "silver bullets", there is a wealth of empirical evidence showing that Cleanroom can lead to dramatic reductions in defect rates, and long-term maintenance costs. The lengthy semi-formal invariants and proofs that it requires will seem like overkill to many, but only because society keeps letting us sell software that doesn't actually work. Sooner or later, we're going to have to meet the same standards as housing contractors and toaster manufacturers. When that happens, I for one will be grateful for the simple, straightforward introduction presented here.

Clemens Szyperski: Component Software
In this exhaustive (and admittedly at times exhausting) book, Szyperski gives an in-depth exposition, comparison, and critique of today's three major component standards (COM, CORBA, and JavaBeans). He also describes what it will take for those technologies to deliver on the promises that were made for object-oriented programming in its early days. The "Foundations" section explains what components are, and what they have to be to allow programmers to use them the way engineers use chips. The "State of the Art" section then looks at where component technology was when the book was written, while the last two sections look at where componentry can go next, and at the business case for components. While the examples are occasionally hard to follow, that isn't Szyperski's fault: as many designers have found out the hard way, simple examples just don't stumbles over the problems that real-world systems encounter.

General Interest

Stewart Brand: How Buildings Learn
This beautiful, thought-provoking book starts with the observation that most architects spend their time re-working or extending existing buildings, rather than creating new ones from scratch. Of course, if Brand had written "program" instead of "building", and "programmer" where he'd written "architect", everything he said would have been true of computing as well. A lot of software engineering books try to convey the same message about allowing for change, but few do it so successfully. By presenting examples ranging from the MIT Media Lab to a one-room extension to a house, Brand encourages us to see patterns in the way buildings change (or, to adopt Brand's metaphor, the way buildings learn from their environment and from use). Concurrently, he uses those insights to argue that since buildings are always going to be modified, they should be designed to accommodate unanticipated change.

Carlton Egremont III: Mr. Bunny's Guide to ActiveX
What can you say about a book that includes lines like:
"The familiar dot '.' symbol from Internet addresses is used in this book to terminate sentences."
along with a side view of a dialog, and (my favorite) the Visual Basic 5.0 splash screen on page 40, which looks suspiciously like a memory access violation message box. Yes, the book eventually runs out of steam, but it's still very funny, and let's face it, where else are you going to read something like:
"...you form windows using forms. A form is a window that you form. At first forms are unformed. You must form your forms using the form designer (formerly the former). In the form former, an unformed form forms a uniform formation of dots..."

Gary Rivlin: The Plot to Get Bill Gates
Rivlin's book is a history of the great white whale that is Microsoft, and the various people who have tried to harpoon it over the years. It begins with the observation that we admire the kind-hearted, but reward the ruthless. He then chronicles the way in which the greatest corporate power struggle of our time has become a name-calling match between third-graders. Unlike many books about Microsoft and its competitors, The Plot is very even-handed---it speaks unkind truths about almost everyone. Rivlin tells his share of Bill Gates stories, but points out that NOISE (Netscape, Oracle, IBM, Sun, and Everyone else) have been just as brutal as Microsoft when they thought they could get away with it. While its view isn't as broad as that of Cringely's Accidental Empires, The Plot is a more thoughtful, and more insightful, book.

Tom Standage: The Victorian Internet
The Internet is not the first technology to make the world shrink: the invention of the electric telegraph probably had a greater effect. By the 1850s, news that had once taken a week to get from Washington to New York travelled in seconds instead. This revolution had at least as great an impact as the one we are going through now, and was at least as misunderstood. In this book, Standage looks at how it all happened, and how it made things change. He is at his best when relating amusing anecdotes, or when he describes the attitudes of professional telegraphers:
"In a sense, the telegraph community was a meritocracy---it didn't matter who you were as long as you could send and receive messages quickly---which was one of the reasons that women and children were readily admitted to the profession.
Replace "telegraph" with "Internet", and typing speed with HTML expertise, and this is a pretty good description of the Web today.

Almost There

These books are all very good, but for one reason or another, they all left me wanting a little more, or something a little different.

J. Craig Cleaveland: Program Generators with XML and Java
Cleaveland's book explores what code generators (like the wizards in Microsoft's Visual Studio) can do, and how to build them using Java and various XML-related technologies. While many old-style Unix programmers sneer at wizards, this style of meta-programming is at least as powerful an abstraction as object-oriented programming, and deserves to be as well known and as widely used. The book's shortcomings, in my opinion, are that its examples are sometimes hard to follow, and that it doesn't pay enough attention to the problem of debugging generated code (or, more interestingly, of dynamically extending debuggers to handle generated code in domain-specific ways).

Patricia Ensworth: The Accidental Project Manager
Ensworth's book is aimed squarely at programmers who find themselves running a development project for the first time. She covers everything from staffing and gathering requirements to tracking progress, rolling out version 1.0, and what should happen afterward. There are lots of templates for bug reporting and other forms, and a fair amount of common sense advice about how to deal with troublesome team members and external politics. While I don't think that the cutesy cartoons of mis-matched sports teams add anything to the book, my real reason for putting it in this section is that it is aimed solely at developers working within large corporate IT departments. Many programmers---most of the ones I know, anyway---work in smaller companies and teams these days, and I think the book would have been stronger if it had included more material to help us cross this particular chasm.

Karl Fogel and Moshe Bar: Open Source Development with CVS
CVS (the Concurrent Version System) is used by many commercial and Open Source development teams. This book does an excellent job of describing how CVS works, and more importantly, of explaining how programmers ought to work in order to take full advantage of what CVS can do for them. Even-numbered chapters describe CVS's commands, options, and internals, while odd-numbered chapters cover design for decentralized development, and the ins and outs of building, testing, and releasing Open Source code. I put this book in the "almost" section primarily because it didn't talk enough about how CVS fits in with other tools, such as configuration and build managers, issue tracking, and the like.

Brian Marick: The Craft of Software Testing
This is my favorite book on testing, but like all of the others that I have read, it leaves me feeling both overwhelmed and unsatisfied: overwhelmed, because its comprehensive coverage is much more than I can absorb, and unsatisfied, because I still don't really know where I, as a developer, am supposed to start testing the software I write. Marick's writing is clear, and his explanations and examples all make lots of sense, but I think this book would have been stronger if it had been organized around one or two particular tools, like Fogel and Bar's book on CVS. That said, The Craft is a solid tutorial and reference for QA professionals.

Steve McConnell: Code Complete
This classic is a handbook of do's and don'ts for working programmers. It covers everything from how to avoid common mistakes in C to how to set up a testing framework, how to organize multi-platform builds, and how to coordinate the members of a team. In short, it is everything I wished someone had told me before I started my first full-time programming job, and much more specific about details than Hunt and Thomas's Pragmatic Programmer. However, Code Complete was written in a pre-Web era, when desktop GUI programming was still relatively new to most programmers, and Java had not yet been invented. It may still be the best "practical handbook of software construction" around (to quote its sub-title), but I hope that its author will one day update it.

Steve McConnell: Rapid Development
This book is a comprehensive survey of what we actually now about various software development methodologies: not just what their inventors claim, but what has actually been proven. Part I, "Efficient Development", sets the stage for what follows by looking at fundamentals, including classic mistakes. Part II, "Rapid Development", devotes a chapter each to topics such as lifecycle planning, estimation, scheduling, teamwork, feature set control, and getting back on track when things go wrong. Part III then presents over two dozen best practices, each of which is summarized along with the evidence in favor of adopting it. The book closes off with an excellent bibliography. I still refer to Rapid Development frequently, but it is unfortunately showing its age. It is also descriptive rather than prescriptive; McConnell's Software Project Survival Guide and Ensworth's Accidental Project Manager are probably both better choices if you just want to know what you're supposed to be doing.

Bjarne Stroustrup: The Design and Evolution of C++
This book by the creator of C++ is almost unique among writings about programming languages, in that it explains how the language came to be, and what tradeoffs---political as well as technical---were made during its development. Topics include the prehistory of C++, memory management, multiple inheritance, casting, templates, exceptions, and many of the other features that make the language as powerful, and as confusing, as it is. If you've ever said to yourself, "That's stupid! I could design a better language in a weekend!" then give this book a read. My only criticism of it is its age; it would be very interesting to hear Stroustrup's views on these topics now.

Jon Udell: Practical Internet Groupware
Practical Internet Groupware should have been recognized as one of the best books of 1999. In it, Udell (the architect of the original byte.com web site, and one of the creators of O'Reilly's Safari) shows how existing tools and protocols can be combined to create the interactive, collaborative groupware that the World Wide Web was always supposed to be. However, as the author himself would admit, combining existing tools and protocols is a complex, frustrating task that requires both an enormous breadth of knowledge, and a very clear vision of what all this wonderful stuff we've invented could do for us, if we could only see the forest for the trees. Udell's exceptionally gifted writing does as much as can be done to bring the forest into view, but until the tools and protocols themselves are simplified, it will still be a struggle for most readers.

John Viega and Gary McGraw: Building Secure Software
Viega and McGraw, both recognized security experts, start with a simple premise: most computer systems are insecure because of bad software. Their prescription is to write better software by designing in a security model right at the start, to avoid common coding mistakes, to consider the "social engineering" aspects of computer security, and to test for possible security attacks. Given such a broad range of concerns, it is hardly surprising that the book's coverage of different topics is somewhat uneven, but in many places it is excellent. Their chapter on buffer overflow attacks, for example, is a detailed walk-through of how an attacker might find and exploit an unchecked fixed-size input buffer in a program, while their discussion of how to stop help desk staff from giving out information to irate customers (or attackers) is equally useful.

I'm Still Waiting

According to a friend of mine, it's common in many societies for people to respond to drought by making a big show of plowing and planting as if nothing was wrong. The idea is that they can drive cause-and-effect in reverse, and make rain actually fall. Similarly, by writing reviews of books that don't exist, I am trying to trick the universe into bringing the books into existence. I know that sounds kind of silly, but I'm constantly disappointed by how different the books I'm sent aren't. My local bookstore, for example, has seventeen shelves of Java books. If you were to do a set-union on their contents, however, you'd be left with only a shelf's worth of information. What's worse, a lot of things I really want to know wouldn't be there at all. These reviews are therefore my attempt to point out the gaps in the computing literature, and, indirectly, the gaps in most programmers' education (including my own).

Debuggers and Debugging
Despite their ubiquity, debuggers are rarely discussed by either educators or authors. The only book I know on the subject, Rosenberg's How Debuggers Work, brushes over many topics without ever really going into enough detail about any of them. This book, on the other hand, has the same "what" and "how" focus as Levine's Linkers and Loaders. The author starts with a short history of debuggers, and a catalog of their desirable features. She then spends five chapters developing an interactive debugger for Java, and another five on a C debugger for the Pentium. In both halves, topics include setting breakpoints and watchpoints, displaying the contents of memory, tracing execution history by walking through a stack, and so on. Sidebars are used to compare the Pentium to other common microprocessors, and interpreted languages to others (such as C++) in which less information survives to runtime. The book closes off with general material on debugging multi-threaded code, how to debug remote applications, and how to deal with such things as out-of-order instruction execution, dynamically-loaded libraries, and functions with multiple entry and exit points.

The Design and Implementation of Interpreted Languages
This book's premise is that C has taken the place of assembly language for most purposes, and that we should teach it to students in relation to modern interpreted languages just as we taught assembler in relation to Pascal. Over the course of more than 500 pages (the book is clearly intended for use in a full-year course), the author shows how to build a simple virtual machine in C for a small, strongly-typed language that will be immediately familiar to students whose first language is Java or C#. The topics range across pointer arithmetic, array indexing, and memory management, numeric formats, machine-dependent data types, unions, and function pointers. Like Kamin's Programming Languages: An Interpreter-Based Approach, this book builds up its interpreter in stages. Each stage adds another bit of syntax (such as arrays or inheritance), and then shows what has to go on under the hood to make it work. Along the way, students are introduced to the quirks of C, including the use of preprocessor directives to handle platform-dependent code.
Toward the end of the book, the author stops adding features to the interpreter, and starts building support tools for it. The most important of these are a symbolic debugger (which gives her an excuse to talk about object formats), and a profiler which uses both sampling and instrumentation. Results obtained from profiling are used to segue into a discussion of caching, virtual memory, and other aspects of machine architecture that haven't been covered earlier. The final three chapters then wind backward to look at how freely-typed languages, such as Python and Perl, can be implemented. Along the way, the author introduces version control and regression testing, so that students see these key working practices as an integral part of the software development cycle.

Dynamic Storage Allocation
Like Jones and Lins' Garbage Collection, or Levine's Linkers and Loaders, this book is a comprehensive survey of one important aspect of real-world software systems. Its subject is the theory and practice of dynamic storage allocation, from the implementation of malloc and free, to the techniques that operating systems use to put files onto disks. Throughout, the authors hammer home two cardinal rules:
  1. machine-independent programming gives machine-independent performance, and
  2. big-O algorithm analysis will only get you so far---asymptotically inferior algorithms will often deliver better performance in the real world.
This book is not for the light-hearted, or for those who lack the stamina to read through eleven successively more complex refinements of a thread-safe heap. However, it is a great introduction to the build-profile-think-refine cycle that key system components must be put through.

The Extensible Programming Environment
It doesn't matter what the question is these days; XML is probably part of the answer. Everything from GUI layouts to CAD drawings to digital signatures is now encoded as XML. Everything, that is, except every programmer's most cherished resource: source code. Sure, we'll embed XML-formatted documentation inside comments, or write pretty-printers to colorize and format our programs, but for some reason, we refuse to see that using a flexible, extensible storage format for our documents would bring us the advantages that we're telling everyone else it will bring them.
The first part of this book describes an experimental system in which programs are stored in a customized XML format. The system's editor still shows the syntax we're all familiar with, just as Microsoft Word shows italicized Times Roman rather than a sequence of control bytes. However, the system also allows programmers to embed much more information in their programs, from links to requirements documents and bug reports to class diagrams and before-and-after pictures of data structures. The second part of the book then shows how to use XML's extensibility to extend the language, the compiler, the version control system, and everything else in a uniform way. One of the examples is a code generator, in which code generation directives are written in the same language as the code being generated. Another shows how to embed optimization callbacks in the module that they are to be applied to; these are then picked up by the compiler, and applied to uses of that code. Throughout, the authors repeatedly remind us of Turing's great insight: programs are just data, and we can all be better programmers if we treat them that way.

Groupware
When historians of computing look back on the rise of peer-to-peer services in the early 21st Century, they will probably say that their success owed as much to this book as the rise of Unix in the early 1980s owed to The Unix Programming Environment and Software Tools. In just a few hundred pages, this book shows how to use high-level languages, simple protocols, and XML to create web-enabled components, which can then be connected to create powerful collaborative workspaces. By the end of the book, the simple shared calendar and co-navigation tools of the first two chapters have become parts of an on-line courseware package. Throughout, the author emphasizes the importance of robustness, security, and openness: components should do a few simple things well, they should guarantee privacy against both accidental and hostile probing, and they should be usable from anywhere, by anything. As an example of the latter, the author discusses how many users lost important data, such as email archives and meeting schedules, when various on-line services disappeared during the dot-com crash of '01, and how modern services can provide import and export facilities to avoid similar catastrophes.

New Directions for Integrated Development Environments
Most professional programmers today use some sort of integrated development environment (IDE). Whether it's command-line tools running within Emacs, Microsoft Visual Studio, or a lightweight tool like Python's IDLE, they all support interactive debugging, class browsing, WYSIWYG GUI construction, build management, version control, and... Well, that's about it, actually. Despite the enormous strides programming languages and operating systems have made in the last twenty years, most IDEs still don't contain any tools that a Smalltalk programmer in the early 1980s wouldn't have recognized. This book shows just how much easier our lives could be by surveying tools that deserve a place on every developer's desktop. Examples range from the Data Display Debugger, which can draw block-and-arrow pictures of data structures on the fly, to Sitraka's Threadalyzer, which watches the behavior of threads in Java, and reports on likely errors. A few static tools are also covered, such as Parasoft's CodeWizard (a customizable style checker) and the PyChecker tool that looks for common errors in Python programs. As with most collections, the depth and tone of the articles is varied, but the net effect dramatically highlights just how conservative IDE designers have become.

Programming Paradigms
The editors of this collection begin with the observation that a loss of intellectual diversity can limit an industry's ability to adapt to changing circumstances, just as a loss of genetic diversity makes species more susceptible to new predators and disease. C, C++, Java, and C# are all very powerful languages, but they all share the same basic view of the world when compared with Smalltalk, Prolog, Lisp, Haskell, Icon, and others. These articles examine the paradigms that underlie those more esoteric languages, and show how they can be implemented and applied in conventional settings. The declarative style of Prolog and its successors, for example, can easily be captured by overloading overloaded operators in C++, and then used to smarten up search engines in on-line help systems. Similarly, the functional composition style of Haskell and ML is a powerful way to build parsers in Java or C#. At its core, this book is not so much about languages as it is about how different tools encourage us to see the world in new ways.

Real-World Programming
Real-World Programming is a practical guide to those parts of real programs that most textbooks leave out. The first two chapters cover basic error handling: how to structure programs to deal with error codes from operating system calls, the design of an exception class hierarchy, and examples of when and why to throw exceptions. Chapter three covers error handling in threaded systems, while chapters four and five look at common errors in networking protocols and remote method invocation (RMI) respectively. Chapter six then examines how to deal with errors in automatically-generated code, such as the parsers created by tools like yacc. Chapter seven moves away from error handling to examine persistence. The author introduces the problem by looking at ways of saving window positions, font sizes, and the like between application sessions. The examples are all written in terms of the Windows registry, but the ideas could easily be applied to other systems. Chapter eight then describes a simple scheme, similar to the one used in the Microsoft Foundation Classes, which allows arbitrary sets of objects to be saved to a file, and then restored. The book closes with a look at how libraries and applications can report their own versions, and check the versions of the things they depend on. Most of the examples in the book are in Java, but there is enough C++, C#, Visual Basic, and Python to show how to apply the ideas in those languages as well.


Recommendations

Joshua Bloch: Effective Java. Addison-Wesley, 2001, 0201310058.

Don Box, Keith Brown, Tim Ewald, and Chris Sells: Effective COM. Addison-Wesley, 1999, 0201379686.

Stewart Brand: How Buildings Learn: What Happens After They're Built. Penguin USA, 1995, 0140139966.

Elizabeth Castro: XML for the World Wide Web. Peachpit Press, 2001, 0201710986.

Nigel Chapman: Perl: The Programmer's Companion. John Wiley & Sons, 1997, 047197563X.

J. Craig Cleaveland: Program Generators with XML and Java. Prentice Hall, 2001, 0130258784.

Robert X. Cringely: Accidental Empires. Harper Business, 1996, 0887308554.

David Cross: Data Munging With Perl. Manning, 2001, 1930110006.

Carlton Egremont III: Mr. Bunny's Guide to ActiveX. Addison-Wesley, 1998, 0201485362.

Patricia Ensworth: The Accidental Project Manager: Surviving the Transition from Techie to Manager. John Wiley & Sons, 2001, 047141011X.

Karl Fogel and Moshe Bar: Open Source Development with CVS (2nd ed.). Coriolis Group, 2001, 158880173X.

Martin Fowler et al: Refactoring: Improving the Design of Existing Code. Addison Wesley Longman, 1999, 0201485672.

Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides: Design Patterns. Addison-Wesley, 1995, 0201633612.

Joseph N. Hall with Randal L. Schwartz: Effective Perl Programming. Addison-Wesley, 1998, 0201419750.

Andrew Hunt and David Thomas: The Pragmatic Programmer: From Journeyman to Master. Addison-Wesley, 2000, 020161622X.

Jeff Johnson: GUI Bloopers. Morgan Kaufmann, 2000, 1558605827, 2000.

Richard Jones and Rafael Lins: Garbage Collection: Algorithms for Automatic Dynamic Memory Management. John Wiley & Sons, 1996, 0471941484.

John R. Levine: Linkers and Loaders. Morgan Kaufmann Publishers, 2000, 1558604960.

Mark Lutz and David Ascher: Learning Python. O'Reilly & Associates, 1999, 1565924649.

Brian Marick: The Craft of Software Testing. Prentice Hall PTR, 1997, 0131774115.

Steve McConnell: Code Complete: A Practical Handbook of Software Construction. Microsoft Press, 1993, 1556154844.

Steve McConnell: Rapid Development. Microsoft Press, 1996, 1556159005.

Steve McConnell: The Software Project Survival Guide. Microsoft Press, 1997, 1572316217.

Scott Meyers: Effective C++ (2nd ed.). Addison-Wesley, 1998, 0201924889.

Scott Meyers: More Effective C++. Addison-Wesley, 1995, 020163371X.

Scott Meyers: Effective STL. Addison-Wesley, 2001, 0201749629.

Derek M. Powazek: Design for Community. New Riders, 2002, 0735710759.

Gary Rivlin: The Plot to Get Bill Gates. Times Books, 1999, 0812930061.

Doug Rosenberg with Kendall Scott: Use Case Driven Object Modeling with UML: A Practical Approach. Addison-Wesley, 1999, 0201432897.

Doug Rosenberg and Kendall Scott: Applying Use Case Driven Object Modeling with UML: An Annotated e-Commerce Example. Addison-Wesley, 2001, 0201730391.

Robert Sedgewick: Algorithms in C, Parts 1-5. Addison-Wesley, 2001, 0201756080.

Tom Standage: The Victorian Internet. Walker & Co, 1998, 0802713424.

Allan M. Stavely: Toward Zero-Defect Programming. Addison-Wesley, 1999, 0201385953.

Lincoln D. Stein: Network Programming with Perl. Addison-Wesley, 2000, 0201615711.

Bjarne Stroustrup: The Design and Evolution of C++. Addison-Wesley, 1994, 0201543303.

Clemens Szyperski: Component Software: Beyond Object-Oriented Programming. Addison-Wesley, 1998, 0201178885.

Jon Udell: Practical Internet Groupware. O'Reilly & Associates, 1999, 1565925378.

John Viega and Gary McGraw: Building Secure Software. Addison-Wesley, 2002, 020172152X.

Bill Zoellick: CyberRegs: A Business Guide to Web Property, Privacy, and Patents. Addison-Wesley, 0201722305.