The Shape of Things

Dismissing patterns as a programming buzzword is missing the point. Recognizing them during the design phase can help you in the long run.

It all started in 1977. That year, architect Christopher Alexander published A Pattern Language; Towns, Buildings, Construction. In it, Alexander introduced the concept of a design pattern to the language of architecture. A design pattern represents a common way of solving a particular problem, ranging from such small-scale issues as lighting a space in a pleasing manner to the large-scale arrangement of communities in a region. Of these patterns, Alexander says "Each pattern describes a problem which occurs over and over again in our environment, and then describes the core of the solution to that problem, in such a way that you can use this solution a million times over, without ever doing it the same way twice." By identifying patterns that commonly occur in the realm of architectural and urban design, Alexander sought to make it easier for non-professionals to communicate in these realms. Abstracting away the details of a particular building makes it much easier to discuss building in general.

Although Alexander's work has been influential in architecture (and still is; check out his web site at www.patternlanguage.com), for our purposes its major impact has been in computer science. In 1995 Addison-Wesley published Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma, Richard Helm, Ralph Johnson and John Vlissides, who have since become routinely identified as software's "Gang of Four." This book took the design pattern concept and applied it to software, identifying 23 patterns that applied to many object-oriented software systems.

Since then, design patterns have become something of an industry in computer science. A search for "patterns" in Fatbrain's technically oriented bookstore turns up 4,500 titles; a Google search on the phrase "design pattern" gets just over 100,000 hits (a search on the phrase "Britney Spears" gets just over 600,000 hits, so don't be too impressed). A good place to start (although boobytrapped with dead links) is the Patterns Home Page at http://hillside.net/patterns/. Start from there, and you can follow patterns all over the web. You'll find patterns in architecture, design, implementation, user interfaces, and quality assurance. You'll find patterns in every computer language you've ever heard of, and some that you haven't. You'll find pseudo-patterns and anti-patterns. I suspect most of you readers have at least heard of design patterns and the Gang of Four.

Sidebar
Is this sort of column useful to you, or am I just hanging out with the wrong bunch of developers? Write me at [email protected] to let me know! Comments may be used in a future issue of Developer Central, unless you ask me to keep them confidential.

Despite their pervasiveness as buzzwords, though, I find that very few developers really have a solid understanding of patterns. Too often, developers dismiss patterns as templates or recipes for solving a problem, which completely misses the point. I suspect the misconception accounts for the failure of many developers to actually take the time to read and study the Design Patterns book; surely something written six years ago couldn't contain the recipe to solve the problem you're having today, could it?

To get a real sense of the importance of patterns, you have to start with machine language-you know, the actual ones and zeroes running around inside of the computer and telling it to do things. Now, I know most of you have never had the experience, but back in the day the first computer I programmed was an Altair 8800. Programs were input one instruction at a time by flipping switches up for a one and down for a zero (or was it the other way around? Memory fades). The term project was to successfully run a program for integer long division (by repeated subtraction, of course). When you're working in machine language, it's hard to keep track of anything more complex than long division. The focus is just too narrow.

Then came assembler. With an 8080 assembler program, instead of writing 11000010, I could write JNZ, and a program would translate the mnemonic into ones and zeros later. The savings of five characters is insignificant; what matters is that the mnemonic instructions like JNZ and MOVAH and INXH make it possible to think about software in terms of what's going on, rather than in the microprocessor's terms. With assembler, you can get a long division algorithm going in a couple of hours instead of an entire school term.

The next step up the chain of abstraction (and the place where most developers today start) is the high-level language. Now if you want integer division you just write something like intResult = intA \ intB. Interpreters, compilers, and assemblers will turn this into all the ones and zeros you'll ever need. Meanwhile, you're free to grasp a program on a statement-by-statement basis. At this level, you're divorced almost completely from the hardware, and programming starts to become the stuff of pure thought.

One more level up takes you to algorithms and data structures. Just as high-level languages abstract away the details of the underlying hardware, algorithms and data structures abstract away the details of the underlying language. You can take the data structure of a hash table (a plan for storing ten gallons of slop in a five-gallon bucket, just in case you've never run across one) and implement it in C++ or Visual Basic or Lisp or whatever language your boss wants you to use this week. The algorithm for performing a depth-first search of a binary tree is another example of an abstraction that can be implemented in many languages. When you start thinking at this level, software construction becomes a lot more fun. Now, instead of laboring over code a line at a time, you're hooking up B-tree storage to bulletproofed I/O routines and a graphics library. It's like building a house out of prefab parts instead of two by fours.

But sadly, that's where many software developers start: just short of the level of abstraction represented by design patterns.

As defined by the Gang of Four, there are four parts to a design pattern:

  1. The pattern name gives you a way to refer to the entire pattern. That's as important as the step from ones and zeros to assembler instructions. If you share a vocabulary of patterns with another developer, she'll know what you mean when you wonder whether to implement a Decorator or a Strategy in your software.
  2. The problem describes where to apply the pattern.
  3. The solution describes the way to solve the problem. This description tends to be very abstract, couched in terms of objects and classes rather than software implementation.
  4. The consequences describe the trade-offs involved in implementing the solution.

To take an easy example: the Singleton pattern addresses the problem of how to maintain exactly one instance of an object, and to have global state without global variables. The solution is to use a class that always returns the same internal hidden instance when it's asked for an instance. The consequences include the potential benefit of security checking when someone asks for an instance. (That's the stick-figure description of Singleton. In the Design Patterns book, the discussion of Singleton takes eight pages.)

Patterns are not easy. Some of the design patterns in the Gang of Four's book stretch over many pages of discussion and sample implementations (in C+ and Smalltalk). Just understanding the details of a pattern such as Observer can take quite a bit of study.

But there's a payoff to this study: ultimately, design patterns help you solve design problems more quickly. Suppose you're working on the Next Big Desktop Application, and one piece that your team is dealing with is the need to keep a table of data in one window synchronized with a 3D chart of the same data in another window. Your team could spend days in design meetings trying to work out the right combination of objects, events, data structures, and algorithms to meet your goal. Or your team discussion could start out like this:

  • "You know, this looks like a pretty typical instance of the Observer pattern."
  • "You're right. But how are we going to get the unexpected update problem under control?"

The beauty of design patterns is that they make such discussions possible by giving the participants a shared vocabulary at a high level of abstraction. And by encapsulating the wisdom of members of the object-oriented design community who share decades of experience, design patterns help you benefit from that experience as well. You don't need to reinvent the wheel if you have a design pattern that points out how well circular objects roll.

Additional Information

Want to read more of Mike's work? Sign up for the monthly Developer Central e-newsletter, including product reviews, links to web content, and more, at http://lists.101com.com/NLS/pages/main.asp?
NL=mcpmag&o=developer
.

One reason many developers of my acquaintance have managed to remain happily ignorant of design patterns is that Visual Basic and its derivatives are really cruddy languages for the sort of deep object orientation that this stuff requires (there have been attempts at defining Visual Basic design patterns; I'm not aware of any that were vastly successful). That, I think, is about to change. With the coming of the .NET platform, VB and VBA developers have the choice of migrating to VB .NET or C#. Either one offers a language with all the object-oriented goodies you could ever want-and either one presents you with a good reason to get familiar with the patterns literature to increase your effectiveness, and ultimately your salary, as a developer.

comments powered by Disqus
Most   Popular