Often times I find it beneficial to look outside of one's own industry for inspiration. There is often a lot of practical wisdom to be gained from areas that seem unrelated to our own domain, and possibly even similar problems that have already been solved. This has proven valuable to me before, when I was a software developer in the furniture industry - where I found that drawing inspiration from the fashion industry could be helpful in furniture. When working on web apps that render user-customized furniture online, I remember admiring that Nike came out with a particularly impressive user experience for designing and visualizing your own sneaker - a wizard that allowed you to choose colors and styles to make your shoe your own.
I believe this can a helpful exercise for software development in general. As quickly as the industry moves, moments, fads, libraries, even entire programming languages can be fleeting. The break-neck pace of our ever-evolving standards certainly makes it hard to stop to consider that there may be wisdom in other industries, or even within the heritage of our own. Use of design patterns - general, reusable solutions to commonly occurring problems - is an area where I think some extrospection may be beneficial. Specifically, I think looking outside of our own industry can help us understand the simplicity of design patterns as a concept, and better understand their place in the problem-solving process.
The Gang of Four themselves applied ideas from architecture through Christopher Alexander's 1977 book A Pattern Language in their monumental work Design Patterns. A Pattern Language proposed that we create a language around common problems and their solutions. Although specific to architecture, the idea of the work was that other industries such as interior design and engineering can apply the same methodology; and The Gang of Four's Design Patterns was their application of a common pattern language to programming. Thus, one of the most influential books in software engineering is the result of engineers embracing philosophies from other professional disciplines.
It seems with this shift not only the Gang of Four's object oriented patterns, but design patterns in general, are beginning to be questioned. It's not unheard of to hear the opinion that reaching for a design pattern is a recipe for adding unneeded complexity at best, or at worst maybe even stigmatized as typically being a junior developer's over-zealous attempt to apply something they learned in CS school to a situation that doesn't call for it.
Now, there is plenty to be said about the wrong pattern being applied to a problem. But to say it's a problem with patterns in general is surely throwing the baby out with the bath water, and in many situations blaming a problem on the act of using a pattern may also be a case of blaming it on the first thing we see rather than digging further into the problem. It is important to realize that patterns are always a potential solution to a problem, never the solution to the problem. An approach is never going to exhaustively solve all problems; rather it should solve a problem as elegantly and thoroughly as possible while not creating too many others.
But even if we are not reciting ideas from Design Patterns each morning in planning for the next task at hand, software engineers still have common problems to solve on a daily basis - whether object oriented or functional. Just as architects, civil and mechanical engineers, and interior designers do. In any of the above professions and many more, it would be irrational to refuse to identify and apply nomenclature to a common problem that has a common solution. Just as suggested by Christopher Alexander and company in A Pattern Language, we can benefit from having a common design language in our respective fields. By doing so we can focus on the big picture, composing known solutions to known problems, so we can spend more time solving big problems that we haven't thought of yet.
Learning from Others
There is a certain stigma around discussing design patterns, I think, in that they come off as something that should be left behind at school and not discussed at the whiteboard in the office, or that the discussion seems haughty. If you mention a pattern, there is a possibility you'll come off as over-eager, impractical or maybe condescending. Barring some circles that may embrace them more readily, it's certainly not a given that every engineering community will have adopted patterns into their vernacular.
This, I think, is unfortunate. Design patterns are universal to all creative, problem solving disciplines. If you frown when you think of design patterns because your mind conjures an image of hipsters gathered around a whiteboard swirling scotch, twirling their mustaches and discussing the merits of using command pattern for AI behaviors in a video game, it's time for us to take a step back and adjust our expectations.
Here's the proposed idea of a pattern language from the namesake book:
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.
This definition is very approachable, and widely applicable to scenarios that don't require one to have a monocle and a tobacco pipe to find it useful. A pattern consists simply of identifying a common problem, describing it, describing the solution in general enough a way that it can be applied to many different situations in different ways, and naming it. Let's look at a couple examples from the nearly two hundred patterns established in A Pattern Language.
Entrance Transition: Buildings, and especially houses, with a graceful transition between the street and the inside, are more tranquil than those which open directly off the street. - A Pattern Language p.549
This pattern has a name, a common, repeatable problem and an understandable but abstract solution to the problem. The problem is that buildings in which a cozy, homey environment is desired, there needs to be some sort of transition when entering the building so as to help the individual transition from the previous environment to the new environment. You don't want to walk off the street, take two steps and sit on a sofa in front of a fire place. There needs to be an indication that the busy street is that other place and you are entering into this new environment. To accomplish this, you apply the aptly named Entrance Transition pattern to your design by creating an area which gently introduces your guest to their new environment.
This name - problem - solution approach to defining a pattern creates a language that anyone familiar with it can identify by name and determine if it applies or does not apply to the problem they are approaching. What's more, it's defined in such a way that anyone familiar with the domain can understand it - in this case, anyone remotely interested in home design, even your average homeowner. In fact, even the most basic familiarity with the pattern (perhaps reading it once in this blog post) may be enough to cause one to recall it when they encounter a transition space and appreciate the design. Another example:
Indoor Sunlight: If the right rooms are facing South, a house is bright and sunny and cheerful; if the wrong rooms are facing South, the house is dark and gloomy. - A Pattern Language p.615
Again, the definition is straightforward and insightful. Understanding and committing this pattern to memory will at the very least allow one to make more informed choices when house hunting, but I'm sure it also contributes to better, more precise communication for designer and architects. Now let's look at a Gang of Four definition of a pattern:
Prototype: Specify the kinds of objects to create using a prototypical instance, and create new objects by copying this prototype.
- Design Patterns: Elements of Reusable Object-Oriented Software p.133
Again, this definition is structured in a way that we can quickly ascertain name - problem - solution. Let's quickly break this one down. First of all, prototype is an accessible name, familiar to folks acquainted with various disciplines, being applicable to things from test models in the automobile industry to character design in literature. Second, we have a definition which we can immediately determine defines a method of object creation - an object created via the prototype pattern is created as a copy of another object that already exists (already instantiated - state and all).
Hopefully with this comparison of architectural pattern language and software pattern language, it's easier to see that the concept of establishing design patterns is an effort to categorize problems into a language - a vernacular - that communicates clear solutions to the common problems. More importantly, I hope that it demonstrates that it is not, or at least should not, be a badge of academic superiority. If the temptation to be smug for one's knowledge of a pattern arises, perhaps they should ask themselves if the person who chose to include a mudroom on their house's floor plan should feel equally so. Actually, they should feel proud - but because they masterfully applied a tried and true pattern to a common problem, not because identifying that the floorplan needed a mud room was a scholarly act.
Thinking in Abstractions
I'm rooting for a comeback of design patterns. Well I suppose a comeback is impossible because it's impossible to avoid design patterns. When you put RabbitMQ in your stack, you are using event queue whether you know it or not. What I'm rooting for is a comeback of a desire for programmers to have a common pattern language, and to be excited to define, share and communicate them in understandable, accessible ways to their colleagues and the larger community. I'd love to see documentation of a feature that mentions patterns by name that an intern can read and get excited to work in such a collaborative environment that values clear communication. This is what design patterns should get us.
To get here though, we need to be able to identify problems, categorize them, and mentally link them with patterns. We may even need to define a pattern, A Pattern Language-style by establishing name - problem - solution definitions. This requires becoming familiar with and demystifying another concept: abstraction. Like patterns, abstraction is everywhere, used in all industries that deal with same problems over and over again. And like patterns, it's we can look to other industries to take that cold, occasionally soulless tech industry edge off of our idea of it.
First, a definition from Greg Michaelson in his book Functional Programming Through Lambda Calculus:
"[Abstraction] involves generalization from concrete instances of a problem so that a general solution may be formulated.
Perhaps the most simple example of this is something we'd learn fairly early in math. Say we have a word problem where we have two kids having joint birthday parties and they are both bringing all of their friends, and we want to determine how many will be at the party by adding the two groups together. 10 kids will be coming for Alice's birthday, and 13 will be coming for Amy. So we have a 10 + 13 = 23. Now Alice isn't quite sure how many of her friends will come, but Amy is still sure that 13 are coming for her, so now we have a + 13 = b. This is abstraction. We've taken something concrete and we've generalized it. Finally, we account for the fact that Amy might have a different number show up: a + b = c.
The example above is extremely basic, but abstraction is as simple as that. Identify a common pattern with a concrete example, and generalize it. Returning to our contrived example of a + b = c. Any number of fields, both arts and science, can use this abstraction to describe a problem they encounter. The obvious example is what we discussed earlier - mathematics: number + number = number. Now consider a programming example, string + string = string (an application of a + b = c that we wouldn't necessarily think of initially). But this abstraction even applies to an artist's palette: color + color = color - something that is used every time a painter approaches their canvas.
We would struggle to find any skilled trade that does not apply abstraction in day-to-day work. Identifying common problems and solutions and thinking about them in abstractions is a skill that can be helpful to nearly everyone. Even the entrance transition pattern in architecture is an abstraction. Rather than going from one setting directly into another (start => end, street => living room, casino => hotel room), we recognize and apply a different formula to ease the transition (start => transition area => end).
In OOP, we think of classes or objects as our standard method of abstraction, while in functional programming a function would be. But any situation in which a pattern can be identified and a generalized solution formulated is using abstractions. Identifying a potential abstraction and creating it is not an ivory tower exercise, it's a skill that anyone can use and hone.
Towards A Pattern Language, Again
Communicating using a pattern language can benefit us in many ways if we don't neglect or overthink it. Like in other industries, it can help us communicate ideas easily, identify problems quickly, and provides a template to base future patterns on. Utilizing the sunny side of a house to create bright, inviting spaces is not a practice that's going a way. It's a practice that has become so basic (not because it's insignificant, but because care was taken to identify and document it) and well known that we can do nothing but build upon and expand it as a standard.
By observing some patterns established in architecture, I hope that we have demystified design patterns as a concept and we can think of them, not as purely intellectual concepts, but as something we do every day. As software engineers, let's continue valuing the communication and documentation and naming of patterns. It is good for posterity, it encourages continuous education among even the most seasoned of us, it gives us common ground for communication. Let's embrace it - monocles and tobacco pipes are not required.