That's Not an Abstraction, That's Just a Layer of Indirection
by fhur
This page contains highlights I saved while reading That's Not an Abstraction, That's Just a Layer of Indirection by fhur. These quotes were collected using Readwise.
Highlights
There's also a certain asymmetry to abstraction. The author of an abstraction enjoys its benefits immediately—it makes their code look cleaner, easier to write, more elegant, or perhaps more flexible. But the cost of maintaining that abstraction often falls on others: future developers, maintainers, and performance engineers who have to work with the code.
Good abstractions are powerful. They enable us to build complex systems without getting lost in complexity. But we must recognize that abstractions are not free. They have real costs, both in terms of performance and complexity. And if an "abstraction" isn't hiding complexity but is simply adding a layer of indirection, then it's not an abstraction at all.
A useful rule of thumb for assessing an abstraction is to ask yourself: How often do I need to peek under the hood? Once per day? Once per month? Once per year? The less often you need to break the illusion, the better the abstraction.
Abstractions are the enemy of performance. The more layers you add, the further you get from the underlying metal. Optimizing code becomes an exercise in peeling back layer after layer until you finally get to the real work. Each layer represents a mental and computational burden. It takes longer to understand what's going on, longer to find the code that matters, and longer for the machine to execute the actual business logic.
An abstraction is only as good as its ability to hide the complexity of what lies underneath. Think of a truly great abstraction, like TCP. TCP helps us pretend that we have a reliable communication channel, even though it's built on top of an unreliable protocol, IP. It takes on the complexity of error correction, retransmission, and packet sequencing so that we don't have to.
Abstractions are also the enemy of simplicity. Each new abstraction is supposed to make things simpler—that's the promise, right? But the reality is that each layer adds its own rules, its own interfaces, and its own potential for failure.
But what about bad abstractions—or perhaps more accurately, what about layers of indirection that masquerade as abstractions? These "abstractions" don't hide any complexity: they often just add a layer whose meaning is derived entirely from the thing it's supposed to be abstracting. Think of a thin wrapper over a function, one that adds no behavior but adds an extra layer to navigate.
If you've ever worked on refactoring or improving performance in a software system, you've probably run into a particular frustration: abstraction-heavy codebases. What looks like neatly organized and modularized code often reveals itself as a labyrinth, with layers upon layers of indirection. The performance is sluggish, debugging is a nightmare, and your CPU seems to be spending more time running abstractions than solving the actual problem.
Want more like this? See all articles or get a random quote.