Hello! I’m Ben Christel, and you’re reading Ben’s Guide to Software Development.
This newsletter is ostensibly about my book, Process to Processes. For the last couple of months, though, I’ve taken a detour from the book to think more deeply about how the architect-builder Christopher Alexander’s ideas apply to software development. If you missed those posts, here they are in chronological order:
Some of you may be wondering: is all this Alexandrian stuff going to be in the book?
My current answer is “no, not all of it.” There will probably be a chapter on centers, but that will most likely be it. I started this series on C.A. with a simple goal: to find out if introducing the concept of centers in the book would be likely to pay off in concision and precision. I think I have my answer: it will. But now, having gotten the answer, I feel kind of obligated to finish this series before returning to book-writing. Hence, this post.
I’ve gotten positive feedback about this series, and it’s clear that many of you find C.A.’s fifteen properties of living structure as fascinating as I do. I’m not planning to include the fifteen properties in the book, though. The main reason is that I think they’re too difficult for newbies to use effectively. Instead, I’ll be writing about specific design tactics that exemplify the fifteen properties, without actually mentioning the properties themselves. A few examples of those design tactics (and the properties they exemplify):
Code that fits in your head (Levels of scale)
Parse, don’t validate (Boundaries)
Anti-corruption layer (Boundaries)
Adapter (Boundaries)
Domain modeling (Strong Centers)
Type-driven and test-driven design (Positive Space)
Objects as state-containers (Boundaries, Strong Centers)
Generalization, and separation of concerns (Contrast)
Symmetry (Local Symmetries)
Functional pipelines (Alternating Repetition, Good Shape)
It probably bears re-emphasizing that the fifteen properties are not metrics to optimize. They are descriptive, not prescriptive; they’re the effect, not the cause. We can’t create good software by trying to create the fifteen properties — but when we try to create good software, the properties tend to follow.
The problem with C.A.’s fifteen properties is that they are distractingly picturesque. I worry that if I included them in the book, readers would obsess over them, and they really shouldn’t. In spite of the 10,000 words I’ve written for this series, creating the fifteen properties takes about as much effort as sneezing. They are nearly always the result of resolving an irresistible urge in (what seems to an expert practitioner to be) the most obvious way.
If there’s a theme that unites properties 12–15, it’s the idea of doing the most natural thing. Designing maintainable, adaptable software doesn’t require extraordinary creativity, inspiration, or genius. It just requires awareness of the forces in the system, a vocabulary of design moves, and patient effort.
12. Echoes

There are certain ideas from computer science that show up again and again in software systems, and at many different levels of scale. These ideas seem timeless—inseparable, perhaps, from the nature of information itself. Some examples:
Processes → echoed in Go’s goroutines, generators in JavaScript and Python, and Ruby’s blocks.
Objects and message-passing → echoed in services and API calls.
Queues of messages and events
Actors, which are processes + objects + queues
Graphs, and especially trees
Parsing (transforming data from less structured to more structured, with a possibility of failure) and presentation (transforming the other way)
Self-stabilizing feedback systems; eventual consistency
Polling vs. notifications
Extract-Transform-Load → echoed in James Shore’s Logic Sandwich pattern (gather input, compute, write output)
These ideas are larger than electronic computation; their application extends to (or, more likely, is inspired by) human communication patterns.
A company made up of many teams or departments can be modeled as a bunch of objects sending messages to each other.
The outermost feedback loop of the software development process is mediated by humans, who are ultimately the ones who must stabilize the system when things go wrong.
An ordered backlog of work items is a priority queue that communicates between the product manager and the engineering team.
…and so on.
When you can see the echoes in different parts of the system, you have more places to get design ideas from. This makes designing easier and more joyful. As Christopher Alexander wrote,
Often, when all the different details are members of a family, the task of making the building becomes simpler, the rhythm of making it faster, more economical. It can produce the necessary variety without trouble. If, on the other hand, the details are disparate, it is such an effort, mentally, to make the building at all, that there is less room for variation and invention. The result: in a building without echoes, the final adaptation of the building to its needs is often weaker.
—The Phenomenon of Life, p. 221
Using an echo of an existing solution sometimes doesn’t feel very creative, and that’s fine. The general principle, in both software and buildings is: keep the broad strokes boring — trite, even — so you can focus your attention on the details that really matter to the user experience. Users aren’t there to appreciate the structure of your building or software application. They don’t care how innovative or interesting that structure is if it doesn’t improve their experience.
13. The Void

A void might seem intuitively to be the opposite of living structure — empty space is about as dead as you can get. However, the purpose of a void is not to remain void, but to create an environment where life can bloom. This happens in two ways:
Smaller, temporary structures can fill in the void. This happens, e.g. in a town square, which might be filled at different times with people, vehicles, tables, or market stalls.
The void can form a contrast with finer structures at its margin or in its center. The contrast intensifies the life of the whole configuration.
Christopher Alexander said of voids that
differentiation of minor systems almost always occurs in relation to the “quiet” of some larger and more stable system
and so it is in programming. The most significant systems in programming are also the quietest. Operating systems and programming languages are glacial, graceful beasts. The slowness of change in these systems creates the conditions for life — i.e. software applications — by providing a stable platform on which they can grow without being constantly disrupted. Innovation can bloom when platforms change slowly, and are unopinionated, quiet, and “empty.”
A programming language or library creates a metaphorical void in another way: it defines a space of hypothetical or potential programs, and this space “wants” to be filled by living structure. For more on this idea, I recommend watching Sarah Perry’s excellent and mind-bending talk “How to See Voids.”
Alexander thought voids had a spiritual quality - the sacredness of the void is communicated through its utter quiet. I don’t really know how to create this quality in code — except, perhaps, through the next property, simplicity and inner calm.
14. Simplicity and Inner Calm

One property that consistently marks the code of master programmers is calm.
Novices’ code tends to be tortuous: full of surprises, complexities, and odd bits sticking out. Data gets transformed and then untransformed a moment later. The call graph feels like a maze. APIs aren’t orthogonal; every method call seems to have side effects that often have to be compensated for or explicitly prevented. The whole system feels feverishly, frantically busy — yet not much is actually accomplished.
Dysfunctional software development systems have the same frantic feeling. Constant firefighting, miscommunication, elaborate plans and Gantt charts, blame, unclear priorities, and a general miasma of despair pervade teams cobbled together by managers who don’t really have a clue how to make software development work.
Calm is the opposite. Calm is about working with unhurried efficiency, doing just what is needed and then stopping. The masters make this look easy, but it takes practice.
Whenever I think about simplicity and calm, I’m always reminded of this story from Zhuangzi:
Ting the cook was cutting meat free from the bones of an ox for Lord Wen-hui. His hands danced as his shoulders turned with the step of his foot and bending of his knee. With a shush and a hush, the blade sang following his lead, never missing a note. Ting and his blade moved as though dancing to “The Mulberry Grove,” or as if conducting the “Ching-shou” with a full orchestra.
Lord Wen-hui exclaimed, “What a joy! It’s good, is it not, that such a simple craft can be so elevated?”
Ting laid aside his knife. “All I care about is the Way. If find it in my craft, that’s all. When I first butchered an ox, I saw nothing but ox meat. It took three years for me to see the whole ox. Now I go out to meet it with my whole spirit and don’t think only about what meets the eye. Sensing and knowing stop. The spirit goes where it will, following the natural contours, revealing large cavities, leading the blade through openings, moving onward according to actual form — yet not touching the central arteries or tendons and ligaments, much less touching bone.
“A good cook need sharpen his blade but once a year. He cuts cleanly. An awkward cook sharpens his knife every month. He chops. I’ve used this knife for nineteen years, carving thousands of oxen. Still the blade is as sharp as the first time it was lifted from the whetstone. At the joints there are spaces, and the blade has no thickness. Entering with no thickness where there is space, the blade may move freely where it will: there’s plenty of room to move. Thus, after nineteen years, my knife remains as sharp as it was that first day.
“Even so, there are always difficult places, and when I see rough going ahead, my heart offers proper respect as I pause to look deeply into it. Then I work slowly, moving my blade with increasing subtlety until — kerplop! — meat falls apart like a crumbling clod of earth. I then raise my knife and assess my work until I’m fully satisfied. Then I give my knife a good cleaning and put it carefully away.”
—Translated by Sam Hamill and J.P. Seaton (The Essential Chuang Tzu, 1998)
Elsewhere, I wrote:
Like the master butcher of Zhuangzi's parable, who cuts the meat where it comes apart naturally and so never blunts his knife, the engineer's goal is to see the structure of the problem as it really is, and then simply lay the pieces side by side. To an observer it seems there is almost no need to cut; no need for a knife. The problem flakes apart under the gentlest effort like perfectly cooked fish.
Here is an example of how this applies to programming. Consider the task of parsing C-style string literals out of a file. A novice programmer might search for strings by looking for quote characters, then looking for backslashes preceding them to figure out whether they are escaped. And then looking for backslashes preceding the backslashes, to figure out whether the backslashes are escaped, in which case the quotes should actually be treated as string delimiters…
A master will probably use a regular expression like this (JavaScript):
const cString = /"([^"\n\\]|\\.)*"/g
This expresses the essential parts of the problem in a single (admittedly terse) line. A string consists of a double quote, zero or more “source characters,” and a closing double quote. A source character is either:
any ASCII character except a double quote, newline, or backslash
a backslash followed by any ASCII character.
The process that evaluates this regex is as simple as its denotation: it grabs all the string literals in one pass, looking at each character only once.
This kind of simplicity is an ideal, rarely achieved. When it is achieved I think it often goes unrecognized, because the solution seems obvious, commonplace, as natural as if it had always existed. But, recognized or not, it is an achievement. To find simplicity and calm is to create a part of nature — and thus to become one, for a moment, with nature itself. I can think of no higher goal in art than that.

15. Not-Separateness
Programs interact with other systems, both human and digital, in the course of their development and use. Their perceived quality is largely a matter of how well they interface with those other systems.
Not-separateness — what we might call good fit — is the property of a system whose interfaces are precisely in tune with the environment. Not-separate systems always arise via careful, incremental adaptation. The system grows out of the environment and responds to it, addressing its needs and accommodating its quirks.
Below is a simple example of not-separateness, from GitHub’s UI. At the top of every pull request, the branch name is displayed beside a button to copy it to the clipboard.
The designers at GitHub know that users often want to copy branch names to paste into Git commands, so they make that as easy as possible. This design choice acknowledges several other centers in GitHub’s environment:
Programmers
Terminals
Git
Branch-based development workflows
The utility of this feature is thus deeply tied to the specific ways that programmers use both GitHub and other development tools. The user interface cannot be separated from the environment where it occurs.
Not-separateness isn’t just a property of GUIs, though; it also occurs in source code. Any time we write code, we’re creating the user interface that our future selves will use to understand and change the code. That interface needs not only to be comprehensible in the abstract, but to be comprehensible through the specific tools (e.g. editors and debuggers) that we actually use.
Here’s an example of how code can fit (or not fit) programmers’ tools: I was once on a team writing C++. We had a coding convention that dictated that all member variables should be prefixed with an underscore, like _someName
. I suggested that we drop this rule, since our IDEs highlighted member variables in a unique shade of purple that made them easy to spot even without a special prefix. My teammates objected: some contributors to our open-source codebase might be using editors that didn’t have that feature. The prefix was for them, not for us. What seemed like good fit to me (accommodating our code style to the capabilities of our tools) wasn’t a good fit in the bigger scheme of things.
The opposite of not-separateness is what we might call stand-out-ness — a much sought-after quality in Silicon Valley. Only something that is separate can be flashy and attention-grabbing. For this reason, software makers seem to favor separateness over not-separateness — they prioritize showroom appeal over actual usability. Bruce Tognazzini has a great write-up of the many ways Apple has done this over the years, optimizing its products for buyers rather than long-term users. Many other companies are guilty of using the same tactic.
Of all the fifteen properties, then, not-separateness may be the hardest for Silicon Valley types to swallow. We want our software to stand out — not just to boost sales, but because on some level we all want, as Steve Jobs said, to “make a dent in the universe.” But what the universe needs is careful mending, not more dents. If ten thousand different people each start a world-changing revolution, the result is likely to be chaos, not utopia.
When products are deeply adapted to their context, innovation isn’t flashy or glamorous. It feels like doing the same old thing in a slightly different way. But the truth is, we never do the same thing twice in software. We are always adapting, refitting, testing out a different strategy or a different order of operations. These tiny innovations seem trivial at the moment of their conception, but over time they add up. They produce incredibly subtle, intricate designs that could never have been planned at the drawing board. And, more importantly, they produce software that users love.
By accommodating themselves to their context, not-separate programs become a kind of image of the forces in that context. Their shape is determined by users’ needs and desires, not the programmer’s ego. As a result, these programs have a special quality. When you use them, they seem to just work the way you’d expect. They work so well, in fact, that most of the time you don’t even notice them.
But if for some reason you do become aware of them, if you do happen to look more deeply, you may be surprised to see the image of your own innermost self, like the imprint of your own thumb, staring back at you.
