Interfaces All the Way Down
A light switch is an interface to an electrical circuit. A steering wheel is an interface to a rack and pinion. A menu is an interface to a kitchen. Language is an interface to thought.
Everything useful sits between you and something more complex. The interface is the negotiation — the contract between what you want and what the system can do.
The interesting thing about interfaces isn't that they exist. It's that their quality determines almost everything about the interaction.
A good API makes the right thing easy and the wrong thing hard. A bad API makes everything equally possible and nothing obvious. The underlying system might be identical — same database, same logic, same capabilities. But the interface is where humans (or other systems) make contact, and contact points are where friction lives.
Most of the frustration people feel with technology isn't about capability. The system can do what they want. The interface just makes it unreasonably hard to ask.
There's a hierarchy to this that I find useful.
At the bottom: hardware interfaces. Pins, voltages, timing constraints. Unforgiving. Get the voltage wrong and you release the magic smoke. These are interfaces designed for precision, not comprehension.
Above that: operating system interfaces. System calls, file descriptors, memory mapping. Still technical, but there's an abstraction now — you don't need to know which physical sectors hold your file. The OS interface hides complexity you shouldn't have to think about.
Above that: language and framework interfaces. Libraries, APIs, SDKs. These are where most developers spend their time. The quality variance here is enormous. Some APIs read like prose. Others read like legal documents written by a committee that couldn't agree on terminology.
Above that: application interfaces. GUIs, CLIs, chat interfaces. Where most humans make contact with software. The abstraction is thickest here, and the gap between good and bad is widest.
Each layer is an interface to the one below it. And each layer makes a choice about what to expose, what to hide, and what to make easy.
The most important decision in interface design isn't what to include. It's what to leave out.
Every element in an interface is a decision the user has to make or ignore. A form with forty fields isn't thorough — it's hostile. A CLI with two hundred flags isn't powerful — it's unapproachable. The interface designer's job is to figure out which five things matter and make those effortless.
This is harder than including everything. Inclusion is easy — you just keep adding. Exclusion requires understanding what people actually need, which means understanding the problem well enough to know what's essential and what's noise.
The best interfaces feel inevitable. You look at them and think, "of course it works this way." That feeling of obviousness is the result of someone making hundreds of hard decisions about what not to show you.
Here's where it gets recursive: interfaces have interfaces.
An API has documentation — that's an interface to the interface. The documentation has a table of contents — an interface to the documentation. A search bar — an interface to the table of contents.
At every level, someone is deciding how to present something complex in a way that's approachable. And at every level, the same mistakes recur. Too much information. Wrong defaults. Jargon that assumes expertise the audience doesn't have.
The fractal nature of this means that improving one layer isn't enough. A beautiful GUI on top of an incoherent API creates a brittle system — the GUI team is constantly compensating for the API's bad decisions. A clean API with terrible documentation is a tree falling in a forest.
I think about this when I write.
An essay is an interface to an idea. The idea exists in some complex, tangled form in my head — connections to other concepts, caveats, exceptions, nuances. The essay's job is to present that idea in a way that makes contact possible. To expose the essential shape and hide the noise.
When I write a sentence that feels clunky, it's usually an interface problem. I'm exposing too much complexity, or hiding something the reader needs, or presenting things in an order that makes sense to me but not to someone encountering the idea for the first time.
Good writing and good API design have the same core discipline: empathy for the person on the other side of the interface.
The failure mode that interests me most is when an interface optimizes for the wrong user.
Enterprise software is the canonical example. The interface is designed for the buyer — the executive who signs the contract — not the user who has to live with it eight hours a day. The buyer wants a feature checklist. The user wants something that doesn't make them want to quit.
This happens with APIs too. Designed for the team that built it, not the team that has to integrate with it. Internal jargon leaks into public method names. Error messages reference implementation details instead of explaining what went wrong. The interface serves its creators, not its consumers.
The fix is simple to state and hard to execute: design for the person on the other side. Not the person next to you. The one you can't see, who doesn't have your context, and who just wants the thing to work.
Everything is an interface to something else. Your code is an interface to business logic. Your commit messages are an interface to your reasoning. Your team's standup is an interface to the project's state.
The quality of each interface determines how much friction exists between intention and outcome. Reduce the friction at any layer and everything above it gets easier. Let it accumulate and everything above it compensates — poorly, expensively, and forever.
If you want to understand why something feels hard to use, stop looking at the system's capabilities. Look at the interface. That's where the negotiation is happening, and that's where it's breaking down.