Getting Back into Writing on My Own Terms
For the last five years, I’ve probably been writing more than ever, which you wouldn’t guess based on my publication schedule on my very own website (spoiler: it’s been four years!). Most of it has happened internally somewhere: multi-page proposals, architecture concepts, or just pull request texts and Slack messages of epic length.
In the last few years of my work, there were only a couple of weeks when I spent working with somebody at the same place at the same time. Some collaboration happens on calls, and these can be really productive for actively collaborating on some code or nailing a particularly nasty bug. Nevertheless, I feel that for aligning, advocating, or documenting, they tend to have a high signal loss. Recording meetings can feel like a solution, but someone will not revisit an hour-long meeting by watching a video; they will rather hit you up on Slack, ugh.
Text, on the other hand, is easily searchable, can be stored along with code, rewritten as needed, and stored for less than a penny.
Why?
One of my favorite methods to drive documentation is asking why relentlessly: Why do we encounter this issue? Why are we solving it? Why is this the approach we took?
Instead of writing a commit message or pull request that explains what has been done, I write why those changes were necessary. The what can probably be summarized by some babbling LLM or, more optimally, by looking at the content. The same applies to code comments: code shouldn’t really need comments about what is being done, as this should be self-explanatory by virtue of naming and structure. A start.before(end)
makes an inline comment unnecessary, which would be needed for code containing copious amounts of boolean algebra.
The aspects of why in code are also much less prone to getting stale than the what. Often, implementations change over time, but the comments stay, leading subsequent readers astray.
The why also makes it easier to spot your own bullshit. If you propose an architecture and the why starts to feel awkward and long-winded, you’re probably offering the wrong thing, and it gives you the opportunity to catch it before somebody else does.
Diagram [noun], ugly image
I think this explains my skepticism about architecture diagrams: they mask everything besides the what. They reduce complex plans into a 2D plane while losing all the fidelity that makes such a diagram necessary in the first place. Even simple assumptions about time relationships in diagrams can break down, which happened to me when I got a diagram created by somebody native in a right-to-left language. After a call, it turned out that I did not need to build a machine that reverses time; I just started to read from the wrong side.
Often, architecture diagrams create an aura of “the difficult grown-up work has been done; now draw the rest of the fucking owl, you coding monkey.” I’ve been guilty of such diagrams myself, one so horrifying that I cannot bring myself to offer it to the general public, as it may make me liable for people being sick. It helped me think about a problem in time-space, but it didn’t offer any sufficient explanation to anybody else. Just recently, I revisited it to re-familiarize myself with it after several years, but I had to read the code since this was much easier to parse than my own drawing.
┌─────────────────┐
│ Transport (net) │
├─────────────────┴──────────────────────────────────┐
│ ┌───────────────┐┌───────────────┐┌───────────────┐│ ┌──────────────┐
┌──│ │ REST ││ Websocket ││ STUN/TURN ││──┐ │ Background │
│ │ └───────────────┘└───────────────┘└───────────────┘│ │ └──────────────┘
│ └────────────────────────────────────────────────────┘ │ │
│ │ │
│ ┌──────────────────┐ ┌──────────────────┐ │ │
└─────▶│ Models │◀─────│ Controller │◀─────┴────────────┘
└──────────────────┘ └──────────────────┘
│
┌────────────┴─────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Database │ │ External │
└──────────────────┘ └──────────────────┘
I do not have a fundamental issue with diagrams, I think. Sometimes I even sprinkle some diagrams into code1, but it has to be like a table of contents, not a pretend-authoritative piece of imagery that inevitably drifts from reality.
If you ever tried to generate diagrams from code, you will have realized that they aren’t as pretty or as useful as you hoped. I don’t think it’s a matter of technique, but rather that the reality of systems is more messy than architecture design wants it to be.
Even AWS fell into that trap with CloudFormation Designer, which was supposed to be a simple way of architecting your cloud systems by drawing diagrams. It feels natural at first sight: you drag and drop high-level, prefabricated components onto a canvas. And while the declarative aspect definitely took off with the likes of Terraform, diagram-based design got mostly abandoned.
Text is just so unreasonably effective. And that’s despite the fact that mass literacy is a relatively recent phenomenon: it took until the 1970s for the majority of the world’s population to be considered literate2.
Even if the end product isn’t the text, but a machine, a software, or a YouTube video explaining the merits of a reasonably priced semi-offroad motorcycle, you just know when the writing is good.