Marc's Blog

About Me

My name is Marc Brooker. I've been writing code, reading code, and living vicariously through computers for as long as I can remember. I like to build things that work. I also dabble in machining, welding, cooking and skiing.

I'm currently an engineer at Amazon Web Services (AWS) in Seattle, where I work on databases, serverless, and serverless databases. Before that, I worked on EC2 and EBS.
All opinions are my own.


My Publications and Videos
@marcbrooker on Mastodon @MarcJBrooker on Twitter

A Quiet Defense of Patterns

Twenty years late to the party.

I find myself coming back to Patterns of Software every few years. I think about it often, mostly when I am doing code reviews. One great part is the front matter: a short debate between the author and Christopher Alexander, first author of the much-celebrated A Pattern Language.

The elements of this language are entities called patterns. Each pattern describes a problem which occurs over and over 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. - A Pattern Language, Alexander et al

In some programming circles, Alexander’s book is treated with religious reverence. A kind of Tao Te Ching of oblique anecdotes. Concrete enough to to sound solid, but not enough to be actionable. A source of in-jokes and unhelpful advice. It’s also a source of conflict for this same group, because it was an inspiration for something widely reviled: the Gang of Four book.

No design patterns are necessary. In any language. - Jan Hudec

When Design Patterns first came out, back in the mid-90s, it captivated me. My access to technical books was limited, and I didn’t have a copy of the book itself, but for a short time I was obsessed with the debate about it. It incited anger, it incited self-righteousness, it incited smugness about missing language features. For each of these loud critics, it seemed to have an equal and opposite supporter. From the community’s reaction, I couldn’t wait to read Design Patterns. Judging by the controversy, I felt like it must be a deeply important book, with something profound to say about software and those who build it.

As for literary criticism in general: I have long felt that any reviewer who expresses rage and loathing for a novel or a play or a poem is preposterous. He or she is like a person who has put on full armor and attacked a hot fudge sundae or a banana split - Kurt Vonnegut

In my mind, Erich Gamma was a Martin Luther figure. He had written a book that was creating a whole new church, ripping open old wounds and providing new courage to both sides. Imagine my disappointment when I finally got my hands on a copy. Instead of Luther’s protest, I found a taxonomy written by stamp collectors.

My overall bias is that technology, science, engineering, and company organization are all secondary to the people and human concerns in the endeavor. Companies, ideas, processes, and approaches ultimately fail when humanity is forgotten, ignored, or placed second. Alexander knew this, but his followers in the software pattern language community do not. Computer scientists and developers don’t seem to know it, either. - Richard P Gabriel

Gabriel is right about how many of us have missed the point of Alexander’s work. We’ve seen it as an exercise in taxonomy, or phylogeny, and missed the fact that it’s primarily a human, rather than technical, endeavour. We should go looking for that aspect of it again, because the human side of our field is broken. We could use all the help we can get. We’ve also missed the range of scale of Alexander’s work, concerned with patterns from the deeply technical to broad ideas with scope across entire societies. To live up to Alexander’s vision in our own field we would need to be doing something much deeper than the Gang of Four did. Design Patterns isn’t software’s A Pattern Language.

The more we can feel all the connections in the language, the more rich and subtle are the things we say at the most ordinary times.

Design Patterns isn’t software’s A Pattern Language. It doesn’t have to be. The concept is much more useful.

The most obvious way that it’s useful is in enabling high-bandwidth conversations by building shared context. Two people with a common set of patterns find it easier to communicate - even if the goal is to reject certain patterns - than those without one. Another advantage, and common area of criticism, is in education. Teaching common patterns makes people more effective communicators, and naming and classifying patterns makes them easier to teach.

A third advantage, perhaps less obvious, is that writing down our shared context lowers the barrier to entry. High bandwidth conversations are needed for efficient teamwork. Effective teams build, and use, a shared context. This is healthy for the team, but can make it difficult to break in. Context can become an impenetrable shield that makes it more difficult to bring others into the group. Whether we intend it or not, this can make groups appear exclusive or exclusionary.

Functional languages are extremely expressive. In a functional language one does not need design patterns because the language is likely so high level, you end up programming in concepts that eliminate design patterns all together. - Slava Akhmechet

Describing and naming patterns is a powerful way to build context, but is not exhaustive. There is no risk of getting to the point where we have described all patterns, and reduced all communication to references to patterns. Context can’t replace communication. At the same time, a list of common patterns isn’t a monotonically growing thing. Patterns are frequently split, combined, superseded, replaced, destroyed or forgotten.

Patterns themselves are also dependent on context. Some apply well to object-orientated programming, some to functional programming, some to running design meetings, some to mentoring and some to building large-scale systems. This isn’t a weakness of the idea of patterns, but a strength. They are sensitive to scale, too. Some patterns of success at one scale, or in one context, may be patterns of failure at another scale, or in another context. Claims that a particular list of patterns is complete, either in support or criticism, are likely wrong.

16 of 23 patterns have qualitatively simpler implementation in Lisp or Dylan than in C++ for at least some uses of each pattern. - Peter Norvig

While recognizing different scales of patterns is critical, they can’t be totally ordered by scale. The debate around patterns-as-flaws in programming languages appears to make this mistake: claiming superiority by demonstrating that some patterns are irrelevant due to their scale. This school of thought then claims that the patterns at their scale and above are not indeed patterns, because they have no use of patterns.

This thinking is flawed in two ways. The glaring flaw is in the restrictive definition of patterns. The more subtle flaw is in not recognizing that they have patterns of their own at similar scales to the ones that were rejected. Abstraction is extremely powerful, but operating at higher levels of abstraction doesn’t appear to imply higher productivity or reduced needs for patterns as a medium for sharing context.

Design patterns are a form of complexity. As with all complexity, I’d rather see developers focus on simpler solutions before going straight to a complex recipe of design patterns. - Jeff Atwood

Shared context and communication is important, but so is programmer productivity. As we well know, productivity comes from more than the ability to type fast. More than any other factor, productivity comes from solving the right problems. Sometimes that means using solutions that exist in libraries or the platform. More often that means re-using solutions we’ve found before, or ones we’ve learned from others. Being productive requires two things: a rich mental library, and the skills to access that library.

A rich mental library can only be built by experience. Experience isn’t best accumulated with, or measured with, time. Instead, it’s built by solving problems and reading and understanding the solutions of others.

As important as the size of the library is the skills to access it. The first step is matching the current problem to the library, or pattern matching. The second step is taking past solutions and adapting them to the exact context. This is seldom a mental (or physical) copy-and-paste exercise. The third part of using this mental library of patterns is taste. Taste means knowing when not to use a pattern. It means carefully adapting patterns to the context of the problem.

Thinking doesn’t guarantee that we won’t make mistakes. But not thinking guarantees that we will. - Leslie Lamport

I love programming. I’ve fallen in love with the craft of programming. I see similar love in the criticism of design patterns (and formal methods, but that’s another topic). That love of craft is great, and important.

When it comes to building working software in the long term, the emotional pursuit of craft is not as important as the human pursuit of teamwork, or the intellectual pursuit of correctness. Patterns is one of the most powerful ideas we have. The critics may be right that it devalues the craft, but we would all do well to remember that the craft of software is a means, not an end.