Small Sharp Tools That Compose
The most durable idea in software is also the simplest: build small things that do one job well, and make them work together. Fifty years on, it still beats the monolith.
Principle Nº One
Build one thing that does one thing. Make it compose.
The most durable idea in software is also the simplest, and it came from Unix fifty years ago: write programs that do one thing well, and write them to work together. The CLI course showed the mechanics — small commands joined by pipes, each handing its output to the next. This principle is about why that isn't just a neat trick, but the most reliable way I know to build something that stays workable as it grows.
Set a small sharp tool next to a monolith — one big program that does the whole job inside itself — and the small tool wins on every axis that matters later. It's easy to understand, because there's only one job to follow. Easy to test, because there's one behaviour to check. Easy to replace, because swapping one piece doesn't disturb the rest. And it's reusable: a tool that just sorts can sort anything, forever, in jobs you haven't imagined yet. The monolith can do none of this — its sorting is welded to its fetching is welded to its formatting, so it's understood, tested, and reusable only all-or-nothing.
Composition is the real payoff
The power isn't in any single tool — it's in what happens when they combine. Four small tools don't give you four capabilities; they give you every useful arrangement of four tools, a far larger number, including combinations you'll discover later for problems you don't have yet. That's why the approach keeps winning: a monolith can only ever do what it was built to do, while a kit of sharp tools does things its maker never imagined. The deep reason it works is a uniform interface — in Unix, plain text streams — a shared seam every tool speaks, so any output can become any input. Build for composition and you're building for the problems you can't see coming.
Don't
Let one tool grow a second job — the sorter that learns to fetch “while it's here.” Every feature added to a sharp tool blunts it.
Do
Reach for a second tool, kept separate, and join them at a clean seam. One clear job per tool; the cleverness goes into the joins.
Where it goes wrong
The common failure is letting one tool slowly swallow its neighbours. It starts honest — a sorter — and then it filters a little, fetches a little, and a year later does everything badly and can't be reused for anything. The opposite failure is over-splitting: fifty trivial tools where five would do, drowning in joins. The aim isn't maximum smallness; it's one clear job per tool and clean seams between them. And composition has honest limits — sometimes a tight, integrated whole beats a pipe of ten parts, and pretending otherwise is its own dogma. Small-and-composable is the default, not a religion.
Put it to work
Take something you've built that does several jobs and try to name each job in one verb. If you find three or four, you've found three or four tools hiding in one. You don't have to split it today — but seeing the seams is the first step, because the next time one of those jobs needs to change, the seam is exactly where you'll wish you'd cut.
Grounded in the Unix philosophy as set down in Doug McIlroy's summary — “do one thing and do it well” — and the pipes lesson of the CLI · MCP · API course.