On Simplicity
Complexity is the natural state of things. Left alone, systems accumulate. Rules beget exceptions. Interfaces grow to accommodate every conceivable use case. The default trajectory of any software that survives contact with the real world is toward more: more features, more configuration, more surface area, more ways to be wrong.
Simplicity requires intervention. It requires someone to look at what has accumulated and decide what doesn't need to be there.
That's the thing people miss when they talk about simplicity as a virtue. It sounds like restraint — like not adding things. But in practice, simplicity is almost always subtractive, and subtraction is harder than addition. Addition only requires a decision about what to include. Subtraction requires a decision about what matters, which means first developing a clear enough understanding of the problem to know what doesn't.
Most people can make something complex. Very few can make something simple.
I think about this in design, but also in code. The simplest function I've ever written was the hardest to arrive at. It does one thing, has one parameter, returns one value, and it took me three attempts and two intermediate versions to get there. Each earlier version was doing too much, or exposing the wrong abstraction, or solving a problem that was actually two problems pretending to be one. The simplicity at the end wasn't a feature — it was a residue, what was left after I finally understood the problem well enough to stop solving the wrong parts of it.
This is why I'm suspicious of simple-looking things built quickly. Real simplicity has a quality to it that's hard to fake — a sense that every part is load-bearing, that there's nothing you could remove without losing something. Quick simple feels thin. Earned simple feels inevitable.
There's a version of simplicity that's actually just incompleteness — where things look clean because the hard cases haven't been encountered yet. This is common in early-stage products. The interface is elegant because it doesn't yet know about the edge cases that will eventually require footnotes and asterisks and "unless you're using this specific configuration" carve-outs. That's not simplicity. That's inexperience.
The simplicity I'm interested in holds up. It's still simple after the edge cases arrive, because it was designed with a clear enough center of gravity that new complexity can orbit rather than erode it.
Getting there requires spending a long time with the problem before touching the solution. It requires asking what you're actually trying to do, what the user actually needs, what the constraint actually is — and sitting with the discomfort of not answering those questions too quickly.
It's slower. It produces less in the short term. But the things it produces last longer, require less maintenance, and tend to compound better. Simple things are easier to extend, easier to reason about, and easier to hand off.
I keep returning to a heuristic I can't fully articulate: simple things feel like they're on your side. Complex things feel like they're waiting to catch you out.
That's what I'm trying to build. Things that feel like they're on your side.