A pattern communicated badly is not a pattern.

A pattern is only valuable when it provides you with the wisdom to know what to expect and how to progress towards a solution. When it is communicated badly, it can hardly be called a pattern. When the problem is not precisely delimited, the pattern will be unrefined and used in more places than it should. When we use a pattern beyond its limit, we dismiss it as lacking because it fails to provide the deep insights we demand from a good pattern.

Patterns can be communicated poorly by not conveying their value. But they can also fail to reveal their value at the right moment. This second part affected the patterns presented by Christopher Alexander as much as it did the software design patterns movement. The patterns in A Pattern Language[APL77] are organised by scale, arranged in a sequence of how they interact. But this sequence is awkward for someone trying to build according to the patterns. The book is organised to educate a reader on the patterns available, not to use as a guide to construction at any particular scale.

Writing to be consumed and keeping the reader in mind is a pattern of its own—one for authors. I know I had to learn it myself and pattern authors are authors, too. The pattern is repeated in many books on how to write as keeping your audience in mind, thinking about what they would value. In this case, pattern users needed some structure for their projects. And this is why the late arrival of The Timeless Way of Building[TTWoB79] was unfortunate. The book provided the necessary motivation and guidance but somehow became the less-referenced text.

But what about not communicating the value itself? How can so many patterns be presented and yet their value not revealed? This happens when a pattern is defined by its solution. The greater the specificity, the harder it is to adapt the solution to our specific problem. The weaker the problem definition, the more effort it will take to ensure the solution satisfies our problem and the more the patterns begin to overlap.

At this point, I want to take a detour into another problem—that of overlapping patterns. There’s nothing inherently wrong with patterns overlapping, but it’s the type of overlap that presents the problem.

Think of it this way: the problems addressed by patterns are generally about complexity. Complexity is about interactions, and the web of interactions spreads far and wide in any actual project. You cannot put a boundary where the interactions stop because they don’t stop. If they did, it would be two separate systems. But patterns help you solve two things. The first is where to put the boundary by asking, ‘Where are the interactions more tractable?’ The second is how to resolve the more complex interactions within that boundary. Thus, the reason why patterns overlap is that they must touch at these more tractable interaction boundaries. This way, we design with fewer variables in mind at any one time.

Pattern Overlaps

Pattern D strongly supports B, C, and E by reducing their overlap.

Patterns should overlap in how they constrain each other. When they don’t, there’s a gap. Another, smaller pattern should fill that gap. But patterns should not overlap in such a way that they solve the same problem. If two patterns are defined by the same problem, then why are they separate patterns?

When you overlap patterns well, the problem being solved is central to one pattern. The other problems around the first problem have their own patterns, which help constrain the solution. But when you have badly overlapping patterns, you find that the patterns are trying to solve the same problem and have different strategies. At that point, you are not using all the patterns together to solve a problem; you are choosing from patterns to solve problems. This is an immediate indicator that what you are working with is not a pattern.

There are quite a few software design patterns that fit this description.

Consider internal and external iterators; the twin patterns of who is in control of the iteration. What is the problem here? Is it the same problem? If not, why did we map them to one design pattern? Now consider the visitor pattern and the interpreter pattern. Are these the same overarching pattern, or do they simply overlap? Does visitor do anything interpreter doesn’t? Depending on your situation, the problem will belong to the domain of iteration techniques or callback techniques. In either case, the problem is all about operations on containers. There is only really one pattern of this, but there are many points of wisdom about it. The problem can be refined when we learn of other forces constraining the solution, such as the pattern of a plugin architecture. With this pattern in place, you need to provide a way to iterate over the containers without necessarily knowing the container type, so you are immediately reduced to iterator factories or callback-style visitor approaches to iteration. This isn’t deciding between different container element visitation patterns; this is deciding which aspects of the problem are constrained by other patterns or which parts of the context significantly change the pattern response.

All that aside, we have to contend with not just the producer but the consumer too. Communication is a two-participant activity. People cannot tell whether they have understood if there is no opportunity to verify their interpretation is correct.

We make this worse when we publish solutions. When you present a solution, you give the answer to a question. You are not providing your ‘working out’. In many patterns, the reasoning is the value in the solution, not the solution itself. Clients pay for solutions. Design patterns are not for clients.

You cannot ship a pattern as a solution in itself. When you attempt to show a pattern via a solution, you miss the reasoning, and the person reading about it does not fully understand why the solution was appropriate to the problem. I find myself repeatedly returning to one of the earliest complaints about design patterns: they were solutions in search of problems.

Unfortunately, even A Pattern Language[APL77] presents some patterns as solutions and names many of the patterns after aspects of the solutions. When we want to teach someone something of value, we don’t furnish them with an answer. This basic fact of teaching should help us understand why the current form of software design patterns is poor communication. We’re not showing our ‘working out’. It is the process of reaching the solution that was of value all along. In the case of patterns, the working out would be the considerations, wisdom, and principles guiding the solution. It is also the steps, the refactoring, providing evidence of the pattern as a process as much as a thing.

Software developers need to know:

  • when constraints will no longer apply,
  • when new constraints will,
  • how any deductions were made,
  • upon what assumptions the decisions were based, and
  • which constraints were not considered.

With this information, developers can determine if the assumptions came true in their case. They can know whether the constraints still apply and whether any new observations have rendered the deductions invalid.

Most software engineers look for shortcuts and automation to leverage value faster. The GoF did the same by cataloguing what they saw and providing it to others to consume. The problem is they collected the patterns and published them, but we needed to understand patterns in general to use them properly. When the book[GoF94] was published, the GoF were not inexperienced developers, but they seemed to get caught up in keeping track of the results and not in the motivation for why the patterns they found existed in the first place.

Clear communication is absolutely fundamental to the value of design patterns. I want to reinforce the importance of understanding that communication is a two-person sport. It’s a collaboration between two minds. One mind takes something of value, the pattern they found value in, and translates it into words in the air, on paper, or on the internet. The pattern sits dormant until someone else reads it, converting it into meaning in their mind. The pattern’s value is reduced or lost if that translation breaks down during either stage.

We should commend the efforts of the pattern community to provide shepherding to those wishing to write patterns. Ensuring patterns were written down such that they could be understood without the author present is obvious in hindsight. However, software developers’ appreciation for the distance between the author and the reader is not deeply instilled. I’m sure only a sparse few pattern writers had any formal training in technical writing. I know I do not. I rely on editors and others to help me make sense when I write.

What the shepherding process did was reinforce the slowly diluting principles of patterns. The lack of a problem-centred design impeded their efforts without them even knowing. They concentrated on ensuring the authors defined the forces, constraints, and solutions well. However, because the movement worked with a solution-centred approach, most patterns either failed to define a root problem or explain the unique wisdom behind their particular solutions.

Design pattern dance party

When you have a big family party, such as a wedding or a large get-together in a very family-friendly environment, there will be adults and kids sharing entertainment. At these street parties or celebrations, you will often get music and embarrassing dad dancing. But you also get children copying the adults. May I suggest something ridiculous? The children are like those reading patterns from a book or website, or being taught about them by someone who thinks applying a specific pattern would solve their current problem.

The children see a finished form of the dance—the performance. They see the adults moving their arms and legs, so they move their arms and legs. They see them lift their arms above their head, so they do that. They see them shake around, so they copy and shake. What they do not see is the rhythm. They do not discern the repetition with variation. They do not grasp the value of keeping time. They do not realise the importance of sticking to a particular area of the dance floor. The children are a mess of waving arms around and wiggling bodies. As far as they can tell, they are dancing, so they are happy and proud of themselves—just like people who first learn design patterns. They can see and understand the solutions, so they begin to apply them wherever they think they fit, not even knowing there is a rhythm to their use.

And then there’s also the fact that the children are watching the other children dance. When they judge the other children, they think they are doing fine. Ask a seven-year-old what they think of an eight-year-old’s dancing skills; they will likely believe the older child dances exceptionally well. This also applies to our budding design pattern user. Surrounded by other people picking them up one solution at a time, they will be commended on their use of patterns by those equally unqualified to discern good pattern usage from bad. Given how few people deeply understand patterns, there’s only a meagre chance of being in a crowd with someone who understands when not to use one. This leads to a spiralling reinforcement of poor pattern usage, overuse, and looking down on people who don’t use patterns all the time. It becomes something of a cargo cult.

Each child and each developer think the other is doing well. All pat each other on the back while generating over-engineered code and horrendous dance moves. They’re using too many inappropriate patterns at the wrong time or making inappropriate patterns with their movements and irregular timing.

At some point, the children grow up and start to discern better. They develop an eye for what makes a good dance and learn the value of rhythm1. They look back at old family videos and laugh at their earlier source code. We should not blame ourselves for being naïve. It’s a given. We should, however, not enable or reinforce the bad behaviour for long. We should find a way to teach the ability to discern more than provide the answers to questions.

The authors of many patterns must have been in a similar situation. They were shepherded by other writers who had been through a process but maybe not entirely understood it. Misunderstanding is more contagious than understanding. Slowly, more and more people understood the core principles less and less, but they could talk about them with great confidence while gyrating wildly in front of other developers.

1

Well, some do. Others become dads.