The missing point of reference

Maintenance can be difficult even when you know the structure of the code and data and why it’s built the way it is. When you are looking at unfamiliar code, it can get much harder. Why is this so? We can walk into almost any house in our neighbourhood and expect to find features in common with our own homes. The design is shared. The design is settled. There’s a long lineage of small adjustments to the design of houses over the ages, but standard components have remained unchanged for centuries. With code, however, so much of the design differed between similar programs, familiarity was highly unlikely. I use the past tense here because things have started to change.

In a house, we don’t design bricks, windows, stairs, or doors. They are the raw materials in most modern homes. Instead, we lay out the rooms and dress them. But there’s only really one layer to the design. In code, we don’t design the assembly instructions, the standard library of our language, or the operating system it’s running on, but we do create layers of design above them all. Your to-do list app will be a UI layer on top of a business logic layer that sits atop a CRUD1 model, which may sit inside or on top of a database access layer. These common layers are familiar to many. They feel like home, so when you find out someone has built something without using them or using something different, it feels alien.

Ancient Greek literate programming

In the past, we lacked these standard materials. We only had bricks. Even though many languages are vying for attention in the full-stack space for developing web, mobile, and desktop applications, they all share similar development and deployment patterns. The request routing, database-backed, CRUD-based, event-driven, model-centric approach to transactional applications is a pattern language. It’s not beyond unreasonable that The Twelve-Factor App could be a pattern language. These layered designs, which we instantly recognise, are the closest we have to classical Roman architecture.

Unfortunately for software developers, these programs only make up a portion of the programs written today. Most embedded development uses a different model. Desktop content creation tools have a different model again. Almost all computer games have a very different structure, and there are many different types of game leading to differing sub-structures at that. There are many other domains with similar stories to tell, far more than I know of, I’m sure. Programs for each domain tend towards a particular style of architecture, but there’s no universal pattern language. Each domain has its own.

This means that for software, there is no singular pattern language. There are many. The search for software patterns and a software development pattern language was doomed to fail by starting from a paradigm. A book on the design patterns of object-oriented design would be like an architectural pattern book on working with bricks. A paradigm is a method or tool you can use to solve your problem; it’s not a problem in itself2. The benefit of patterns was a design process unencumbered by a specific solution.

Why are there so many domains in software when there was only one domain in architecture? Well, the secret is, that’s a false assumption. There are many domains in architecture too. The book is called A Pattern Language, in the singular, for a reason.

Let us finally explain the status of this language, why we have called it “A Pattern Language” with the emphasis on the word “A,” and how we imagine this pattern language might be related to the countless thousands of other languages we hope that people will make for themselves, in the future.

— Christopher Alexander, A Pattern Language, p. xvi.

In many of his projects, Alexander selected and generated patterns constituting a specific language to guide the development. For example, in The Production of Houses[TPoH85] there are 21 patterns in the pattern language with variants specific to the context. The pattern Northeast Outdoor Space appears to be a variant of 105 SOUTH FACING OUTDOORS but with attention given to the needs of the location including both the impact of sunlight and protection from the wind. The patterns Front Porch and Back Porch are also unique to the project. The first was part of the initial language and the other only emerging later when working with the families.

In [Battle12], the pattern language is presented quite differently to that of [APL77]. Gone are the cute, terse names of the older patterns. Instead we have simple but to the point sentence sized descriptions with extended paragraphs to fully enclose their ideal. I saw this as positive progress for patterns simply because good names are impossible to find.

The patterns in A Pattern Language[APL77] are those found in the realm of liveable spaces. The patterns don’t fully account for military installations, medical facilities, prisons, or schools. Some of them apply simply by virtue of being applicable to almost all buildings made for human habitation. However, the patterns in A Pattern Language never address the layout of airfields or ships. The book applies to a domain. Not all architectural domains, but just one that is rather large.

Software inhabits domains too. Each program generally belongs to one domain. The desktop application, the performance-critical batch processor, and the highly available network cluster management software each have their own pattern language—their own collection of patterns found in the development of a cohesive system within their specific domain.

But there’s absolutely no mention of this aspect in the GoF book[GoF94], and it’s only lightly touched on in the first POSA[POSA96]. So, there are no software architectural patterns because these were the days before you would find many common software architectures in object-oriented codebases. The patterns were all too generic, too fundamental, too much like bricks and screws and not homes or community spirit. The first book I found that started the ball rolling on constructing a complete pattern language was Patterns of Enterprise Application Architecture[PoEAA03]. It’s probably not the first, but it’s the earliest example I found that was close to A Pattern Language in form and function.

Later works reside in different domains with many patterns that help guide you through creation or transformation. Examples include:

  • React Design Patterns[React17] 
  • Node.js Design Patterns[NODEJS16] 
  • Language Implementation Patterns[LIP09] 
  • A Scrum Book: The Spirit of the Game[AScrumBook19] 
  • Patterns in Game Design[PiGD05] 
  • Cloud Native Transformation[CNT19] 

But other pattern language books, such as The Surprising Power of Liberating Structures[LibStruct14] and Fearless Change[Fearless04], were eye-opening because they inhabited an entirely different realm of interaction. Liberating Structures attempts to solve the problems of enabling or coaxing communication out of a group of people when they feel embarrassed, anxious, confused, or stuck. Fearless Change provides patterns for supporting the problems encountered when attempting to bring about meaningful change in an organisation—tactics for overcoming the inertia inherent in established communities.

In both books, there was no product, no building to inhabit, only the minds and culture of a group to transform. But they are pattern languages because they take commonly repeating problems in their domains and provide details on the types of solutions, the consequences, and how they fit into other patterns.

Without pattern languages, it’s difficult to find your way into patterns. It’s hard to find the right place to start when every pattern implementation starts and finishes without an apparent next or previous step in the sequence. The absence of a higher-level pattern structure or a dependent consequence of pattern application leaves the user stopping and starting, lurching through development.

1

CRUD stands for Create Read Update Delete, the fundamental activities in a database. The term turned into a way of thinking about what you need in any record-keeping technology—a way to insert new data, retrieve it, amend it and remove it.

2

I have strong opinions about OOP, but even I wouldn’t say it was a problem which needed to be solved.