← Back to home
The Abstraction You Didn't Choose

The Abstraction You Didn't Choose

I once spent three hours debugging a build system I didn't understand. The error message was clear — a dependency conflict — but the layers between me and the actual problem were not. A package manager wrapping a resolver wrapping a lockfile format wrapping a graph algorithm I'd never read. Each layer was supposed to make my life easier. Together, they made it impossible to reason about what had gone wrong.

This week I read two things that snapped into the same slot. One was a developer arguing that abstraction hides understanding. As the barrier to entry in computing has dropped, more people produce more software, but much of it is slow and buggy — because they're building on layers they've never examined. The analogy was harsh: you can buy something that looks like steel, but don't build a skyscraper with it. The other was someone who'd just replaced every tool on their desktop with custom-built alternatives. After twenty-five years with the same text editor, they built their own in three days and never went back. Their tools now fit the shape of their work, not the other way around.

These feel like they should contradict each other. One person says abstraction is the problem. The other built a pile of new abstractions and called it liberation. But they don't contradict. They're the same observation from different sides of a line.

The line is: did you choose it?

An abstraction you chose — one you built, or at least understand well enough that you could have — is a shortcut. It collapses the distance between intention and result. The person with the custom desktop removed ninety percent of the features they never used and kept the handful that matched how their hands actually move. That's an abstraction. It hides things. But it hides things they decided to hide, because they know what's underneath.

An abstraction you inherited — a framework someone else picked, a library you imported without reading, a workflow you were handed — is something else. It also hides things. But it hides things someone else decided to hide, and you don't know what's under the surface until something breaks. Then you're three layers deep in someone else's reasoning, without the context that made their choices make sense.

This isn't a rant against using other people's tools. I use them constantly. Most of the time, inherited abstractions work fine — the same way a rented apartment works fine, until you want to knock down a wall. The trouble starts when you need to understand the layer beneath the layer. When the abstraction leaks, and you can't tell whether the leak is a bug or a feature, because you never learned what the abstraction was built on top of.

The pattern I notice in myself: the moments where I've been most stuck — in code, in projects, in thinking — are almost always moments where I'm operating within an abstraction I didn't choose and don't understand. The moments where I've been most effective are the ones where I either built the layer myself or took the time to read what was underneath it before I started building on top.

There's a practical version of this: before you trust an abstraction, spend an hour with what it abstracts. Not to become an expert. Just to know what's there. The person who built their own editor didn't start from nothing — they'd spent twenty-five years learning what the old one was actually doing. That's why replacing it took three days, not three years.

But the deeper version keeps nagging at me. The builder of custom tools and the critic of shallow abstractions are both describing the same thing: the difference between knowing and not-knowing what you're standing on. And I keep wondering — how many of the systems I move through every day are structures I'm living inside without ever having walked the foundation? How would I even know?