On Simplicity
Every codebase I've ever touched has had more complexity than it needed. More layers, more abstractions, more configuration, more edge-case handling for cases that never actually edge.
This is normal. Complexity accumulates in the dark, between commits, during meetings when no one is looking.
Accidental vs. essential complexity
Fred Brooks drew this distinction in 1986. Essential complexity is inherent to the problem — you can't make a billing system simple because billing isn't simple. Accidental complexity is what we add on top: the tools, the patterns, the frameworks applied out of habit.
Most of what we fight every day is accidental.
The failure mode is subtle
Complexity doesn't announce itself. It grows as features, as abstractions that seemed wise at the time, as defensive code that handles scenarios that never actually occur.
The subtle failure is thinking that complexity is sophistication. It isn't. Sophistication is knowing which complexity is load-bearing and which can be torn out.
How to fight it
The most effective technique I've found: delete things. Not refactor — delete. If you're not sure something is needed, remove it and see what breaks. What doesn't break can stay gone.
The second technique: read the thing again, one month later. Complexity is most visible to fresh eyes. Your future self is your best code reviewer.
Simple doesn't mean easy
A simple system is one where you can hold the whole thing in your head. Easy to change, easy to debug, easy to explain to someone new.
Getting there is hard work. Staying there is harder. But it's the only kind of software worth maintaining.