Afterwood
There is a perennial question which crops up fairly regularly on Twitter and other social media platforms that questions the value of design patterns. The more clickbait styled tweets will simply declare that design patterns and the similarly titled Gang of Four (GoF) book in particular have little relevance in today’s programming toolbox and therefore you should simply ignore them as an anachronism. The more curious programmer on the other hand hopefully seeks a little more substance but may still struggle to see past a movement which has seen better days and provides little interest in these modern times.
And who can blame them? If you’re a fresh-faced programmer devouring everything the industry has to offer and you come across a book from 1994 with C++ code where the examples pass raw pointers around wouldn’t you be somewhat concerned? While perhaps not quite as dangerous, but still firmly in the realm of “who on Earth still uses that?” territory, you also have a bunch of UML class and sequence diagrams to contend with. (Guess what, UML isn’t dead either, but that’s a topic for another day.) And the final nail in the coffin must surely be the fact that a number of the documented patterns in the seminal GoF book pretty much evaporate the moment you consider that C++ has supported lambda functions for almost a decade. Functors are so last Millennium and the double-checked lock finally works by design – no longer relying on compiler extensions – should you still be inclined to litter your codebase with a Singleton (once a very popular choice but now public enemy #1 for the test driven programmer).
Even Java, which didn’t exist at the time the book was written, but was still hugely popular during the rise of the Design Patterns movement has since sprouted lambda functions and eased the burden of solving some of those recurring problems the book helped to address. And while we’re on the subject of Java some of the blame for people having an aversion to design patterns must lie squarely with that unfortunate practice of naming classes by chaining together the names of any design patterns the class relates to, as if there is some kind of prize for winning “Design Pattern Bingo”. I have personally been the recipient of code from a company’s Enterprise Architect that contained the monstrosity:
public class UnitOfWorkXxxServiceFacadeDecorator
(In this particular instance the entire class hierarchy was replaced by a couple of succinctly named C# extension methods that wrapped a caller-provided closure with the necessary behaviour.)
So, are they right then? Are design patterns a waste of time – a solution to a problem in a context where that context was the early ‘90s and the problem was simply poorly designed programming languages?
No, I don’t think so. The Gang of Four legacy is not some old-fashioned C++ code and a bunch of UML diagrams with large class hierarchies; it’s the ubiquitous language they created. The value was never in how they realized the solution in code but in the vocabulary they chose for describing the recurring problem they identified and the “shape” of the solution they came up with. By distilling the essence into just a single word (in almost all cases), and at most three words (for one), they have given us the power to communicate complex ideas in mere seconds. Can you imagine how much longer your design meetings would be if you had to keep saying “a one-to-many relationship between objects so that when one object changes all its dependents are notified and updated automatically” instead of simply saying “observer”?
Even if some design patterns use terms that already had a fairly established meaning in the software industry, such as Proxy (GoF), Cache (POSA3), and Pool (POSA3), the community has taken those ideas and given them a more usable definition. Instead of leaving them to remain ambiguous they have given them clarity. As Dijkstra once said:
“The purpose of abstraction is not to be vague, but to create a new semantic level in which one can be absolutely precise.”
Each pattern does not exist in a vacuum, but together with other related patterns from the same vocabulary they form a language in their own right that allows people to explore design options in a particular problem space without getting dragged into the implementation minutiae too quickly. Once the foundation patterns in the original GoF text and its ilk, such as the first volume of the Pattern Oriented Software Architecture (POSA) series, had arrived further catalogues appeared that focused on particular topics such as resource management, concurrency, integration, etc. Both the POSA and Pattern Languages of Program Design (PLoPD) series stretched to 5 volumes, with the annual PLoP conference still taking place today despite starting way back in 1994. To paraphrase Mark Twain: any rumours of the demise of the patterns community are greatly exaggerated.
For those happy to contend there is still value in the concept of design patterns, is there still any point delving into the distant past – given what was said earlier about some original patterns now being redundant, does the GoF book still hold any relevance? Absolutely! Section 1.6 alone contains a useful summary of many of the core ideas behind object-orientation including what is probably one of the most significant programming axioms – program to an interface, not an implementation.
However it’s largely a catalogue of patterns and many of those are still relevant to today’s design discussions because the vocabulary is still with us today. The aforementioned “observer” might have matured over the years and more closely resembles its sibling – Multicast, introduced in the follow-up book Pattern Hatching – but it’s still there at the heart of any event driven system. The terms Adapter, Facade, Factory, and Proxy had a life before the GoF and naturally continue to live on albeit with a more refined definition. Iterators are a fundamental part of C++, Java, and C# and Decorators became a key idiom in Python. Decorators in Python are considered to be far less rigid than the GoF definition, more akin to Aspect Oriented Programming, but that might be because the AOP term appears to post-date the Decorator pattern. Either way, there are big similarities in the metaphor, and that aids communication. The one pattern that seems to have gained popularity over the years, no doubt due to the rise of automated testing is Builder. The need to create non-trivial object graphs in tests where the salient details of the test data need to remain clear has led to the adoption of Builder (coupled with fluent interfaces) as a very popular technique.
The Conclusion to the Design Patterns book starts by saying “It’s possible to argue this book hasn’t accomplished much.” I think it’s fair to say that 25 years later you would be hard pushed to agree with this statement. While the example code is dated and the ubiquity of closures in modern programming languages have consigned some of the solutions to the history books the vocabulary appears to be timeless. Their concise vocabulary and the subsequent lexicon it spawned are the real legacy of the Gang of Four and I for one thank them for helping me spend less time in meetings and having more productive design conversations.
Chris Oldwood
17 November 2020
Chris is a freelance programmer who started
out as a bedroom coder in the 80’s writing assembler on 8-bit micros. These
days it's enterprise grade technology in plush corporate offices from
the lounge below his bedroom. With no Godmanchester duck race to commentate on
this year he’s been even more easily distracted by messages to gort@cix.co.uk and
@chrisoldwood.