IEEE Micro © 2009 IEEE.
This time I look at a collection that, according to its editor, is completely different from any other book you've read. That statement is true of any book, I suppose, but this book is unusual.
97 Things Every Software Architect Should Know: Collective Wisdom from the Experts edited by Richard Monson-Haefel (O'Reilly, Sebastopol CA, 2009, 218pp, www.oreilly.com, ISBN 978-0-596-52269-8, $34.99)
Richard Monson-Haefel is a co-author of the O'Reilly books Enterprise Javabeans and Java Message Service. The project grew out of a presentation called 10 Things Every Software Architect Should Know, which he was planning for a No Fluff, Just Stuff symposium. He solicited inputs on a mailing list, and nearly 50 people contributed the "things" that became this book. Each fills a pair of facing pages and includes a contributor photo and brief biography. The regularity of the structure ends there.
The free format allows contributors to formulate their wisdom in whatever ways work best for them. They address a variety of subjects in a variety of ways, but looking at the book as a whole, I see themes emerge. They have very little to say about project retrospectives or managing risk, so I hope they will all read two excellent books from Dorset House. Norman Kerth's Project Retrospectives (Micro Review, May/June 2001) and DeMarco & Lister's Waltzing With Bears (Micro Review Jul/Aug 2003) are essential reading for any software architect.
Communication receives a lot of attention in this book. Udi Dahan of Microsoft, for example, advises you to stand when you speak to a group. It makes people take you more seriously.
Other contributors stress the importance of knowing both the language of the business decision makers and the language of the software developers. Communication failures between the two groups cause many project problems, and these contributors assign to architects the responsibility for making that conversation work.
Norman Carnovale of Lockheed Martin Professional Services emphasizes the importance negotiating with the business decision makers to ensure that mid-project changes don't lead to unrealistic schedules and ultimately to failure. David Muirhead of the Blue River Systems Group recognizes that the business must drive a project, so he advocates developing the kinds of information that business leaders can use to make good decisions. Yi Zhou lays out the elements that make up a strong business case for a proposed expenditure.
Michael Nygard reminds us that we should remember the difference between a negotiation and an engineering discussion. When business decision makers ask "do you really need x," the answer should be "yes" if that's what the analysis led to. In an engineering discussion of the point, you might say "you could do without it if . . ." but business decision makers won't hear the "if" or anything that follows it.
Another communication theme is that architects must manage their own attitudes so that they can engage in open conversations with developers and customers. They must not let overconfidence or arrogance prevent them from hearing the good ideas of others or listening to the specific needs of customers.
Timothy High of Sakonnet Technologies gives advice that is easy to follow but often ignored. He advocates recording the rationale for decisions. He questions the value of most design documentation because it is hard to keep up to date. The rationale for decisions, on the other hand, doesn't require changes and is a valuable resource for the life of the project.
Another theme of the book is requirements. Understanding, examining, and negotiating requirements and turning them into specifications is one of an architect's key jobs. Everyone understands that this process is a negotiation that must balance the needs of customers, funders, and developers. Eben Hewitt puts forth the beautiful metaphor of a consommé -- an extremely clarified broth achieved by repeatedly straining out the solids that cloud it. You must test the language of the requirements again and again until it is clear. This reminds me of the Mary Had a Little Lamb heuristic in Gause & Weinberg's Exploring Requirements (Micro Review, Sept/Oct 2001), another book that all software architects should read.
Many of the contributions boil down to pushing back against stated requirements in various ways. Einar Landre of StatoilHydro advises seeking the value in the requirement. He tells the story of the F-16 Falcon aircraft for which an initial requirement was speeds of Mach 2 to 2.5. By asking why, the contractor was able to change the requirement to an agile aircraft that can accelerate quickly to escape from combat. Similarly, Eben Hewitt tells you not to rush to solve the problem. First interrogate it to see if you can change it into a more tractable one.
Keith Braithwaite of Zuhlke exhorts us to quantify requirements. Fast, responsive, and extensible, for example, are terms that mean different things to different people. Developments based on such terms can lead to serious disputes at acceptance time.
Assumptions, as we all know, can be dangerous. Timothy High advises us to challenge assumptions, especially our own. Urban myths -- or even facts that used to be true -- can lead us away from excellent solutions to design problems.
Not all requirements can or should be satisfied. Good design involves tradeoffs. Mark Richards of Collaborative Consulting recounts the story of the Vasa, an early 17th century Swedish ship that satisfied all of its requirements and sank the first time it fired its guns. Bill de hÓra of NewBay Software says that requirements often come in threes (like fast, cheap, and accurate) and that you should be prepared to pick two and jettison the third. When a requirement seems absolute, be skeptical and ask why. Dave Quick of Thoughtful Arts puts it another way: Scope is the enemy of success. The greater the scope, the worse the chances of success.
Another way to test requirements, according to Stephen Jones, is to stretch key dimensions to see what breaks. This kind of stress testing can identify future problems long before they occur. It enables the necessary changes before the design becomes set in stone.
A number of contributors show concern for end users. Your customer may not be the end user, as Eben Hewitt points out, but your customer won't succeed if the system serves end users poorly. Keith Braithwaite, following Heidegger, uses the german term zuhanden to suggest that systems should be invisible to users. However, Steve Talbott in Devices of the Soul (Micro Review, July/Aug 2007) takes the opposite point of view: Because it is so important to remain conscious of the assumptions and unseen factors that affect us, it's a good idea not to forget about our tools. An invisible tool still embodies the ideals and assumptions of its creator.
Many contributors offer advice about pitfalls and how to avoid them. Avoiding unnecessary complexity or generalization is a common theme. Neal Ford of ThoughtWorks defines accidental complexity as the complications that arise as byproducts of addressing the essential complexity of the problem. Often accidental complexity comes from adopting frameworks that are too general or fail to match the problem.
Kevlin Henney puts it another way: simplicity before generality, use before reuse. Eric Hawthorne says to choose frameworks that stick to their own domain and don't impose unnecessary requirements. Keith Braithwaite points out that the real world has multiple, inconsistent, overlapping frameworks. Sometimes it works to use each in its own domain. Or as Randy Stafford of Oracle puts it, there is no one-size-fits-all solution. Exercise contextual sense to understand what works in a given domain.
The editor of the book, Richard Monson-Haefel, contributes his own pitfall. Avoid trying to future-proof the system, because you can't predict the future. Trying to guess the technologies of the future can lead to analysis paralysis.
Design and Development Approaches
As you would expect in a book about architecture, design and development approaches receive a lot of attention. Most contributors implicitly or explicitly advocate iterative and incremental processes. Bill de hÓra summarizes this view by saying that great software is grown, not built. Similarly, David Bartlett advocates Martin Fowler's continuous integration (CI) approach, which includes automated builds and testing at frequent intervals.
Dan Chak of CourseAdvisor, however, focuses on designing the underlying database. He feels that the data structures and relationships that underlie applications do not evolve rapidly and require a complex, comprehensive technical design up front. The resulting solid and self-protective data fortress will save application data from the inevitable bugs in the application level.
George Malamidis of TrafficBroker adopts the language of business. He says that every architectural decision is an investment. You should consider the return on investment (ROI). This is true whether you use an agile process or the waterfall model.
George Holpe of Google says welcome to the real world. He implies that most software engineers are clinging to a bygone world of predictably ordered processes controlled by the program rather than by external events. In that world, systems are tightly, rather than loosely, coupled. He quickly tears down that straw man, using the word "scary" a couple of times to characterize the new environment. I get his point, and he's certainly right about the need for distributed, loosely coupled, event-driven systems, but I'd like to point out that we were building event-driven systems in the 1960s, so the idea isn't all that new.
Several other contributors also use uncertainty to their advantage. Kelvin Hanley suggests than when you come to a fork in the road, design so that choosing between the two branches has fewer consequences. Erik Doernenberg of ThoughtWorks suggests trying both branches and deferring the choice until it's obvious which is better.
Performance and Maintenance
Most of the life of a successful software project happens after its initial installation. Many of the contributors address issues about performance and maintenance.
Randy Stafford points out that application architecture determines performance. Rebecca Parsons of ThoughtWorks advocates beginning performance testing early in the development process. This can help you identify problems early. It also gives you an ongoing record that shows which changes helped or hurt performance. Craig Russell of Sun Microsystems takes a broader view and advocates looking at the performance of the developers implementing the design.
Tools and Techniques
I don't have room to go into all of the suggestions about tools and techniques. One that tickled me is Paul Homer's suggestion that you can get a good idea of how a system works by looking at its underlying data structures. In 1967 I attended Butler Lampson's course on operating systems at UC Berkeley. Lampson made exactly that point.
Many contributions address the necessary qualities or skills of software architects. Many see themselves as leaders of the development project and focus their comments on how to interact with developers. Many say to lead by example or to keep a hand in the development work. The objectives are to maintain the respect of the developers and to experience the design from the point of view of a developer. It's easier to recognize design mistakes if you're the one who has to implement them.
Many stress the importance of maintaining respectful and open relationships with developers. Evan Cofsky of Virgin Charter invokes a taxonomy in Neal Stephenson's Cryptonomicon. Architects are kings and must provide opportunities for elves, dwarves, and wizards.
Many also look at the social or ethical aspects of an architect's work. Barry Hawkins advises valuing stewardship over showmanship. As he points out, you are playing with other people's money. Michael Nygard points out that many decisions restrict or enable end user behavior. A few days of programming time may save end users a few seconds each time they use a feature. With many users and many repetitions, that could be a huge savings for them, but at a cost that you won't recoup. It certainly raises an ethical question.
Yi Zhou tells architects to take responsibility for their decisions. That means putting it in writing and communicating it to everybody it affects. You must also follow through to ensure that developers implement your decision, and you must review the decision periodically to see how it's working out. Taking responsibility also means not making decisions that you're not qualified to make. Delegate those decisions to experts.
I hope this review gives you an idea of the flavor of the book. If you design software, you're sure to find enough nuggets of information in it to justify its price many times over.