On Finished Software
There’s a moment in every project. The tests pass. The UI feels right. You’ve used it yourself for a week without hitting an edge case. You think: this is done.
Then you add a README. Then a license. Then you realize the config file format is inconsistent. Then someone (you, three months ago) files an issue about an error message that makes no sense. And suddenly it’s not done, it was never done, software is never done.
The myth
I keep building tools for a hypothetical “finished” state. Clean abstraction boundaries. Configuration over hardcoding. Extensible plugin systems. All good practices, but sometimes I suspect I’m not preparing for real flexibility—I’m just avoiding the discomfort of saying “this is what it does, and it doesn’t do that.”
A counter-example
I have a script. It’s 200 lines of Bash. It backs up my VPS to S3. It has no tests, no config file, no flags. I wrote it in 2019. It has never broken. I have never wanted to extend it. It is, by some definition, finished.
What’s different? The problem is bounded. Backup a specific set of directories, daily, to a specific bucket. If those constraints change, I’ll write a new script. The value is in the specificity, not the generality.
What I’m trying now
Explicit constraints. For side projects, I write a “scope statement” in the README: This tool does X for users who need Y. It explicitly does not do Z. When I want to add Z, I have to argue with past-me in a commit message.
It’s not foolproof. Past-me is persuasive, present-me is eager. But it slows me down, and sometimes that’s enough.