Perfect Software: Desirable or Overkill?
Software has never been perfect, and it never will be. The question has always been how close to perfect is sufficient, and whether anything beyond that is worth paying for. For most of my career, that question answered itself, because everything beyond sufficient consumed additional time, money, and resources that somebody had to approve. AI has changed the math. The extra feature, the extra option, and the extra test are close to free to generate now, and when overkill stops costing much to create, scope creeps on its own.
Creeping Scope
I watched it happen on someone else’s pull request before I noticed it on my own. A developer asked their AI stack to add a feature and got back the feature plus three more nobody had requested. Configuration options for cases that don’t exist yet. Error handling for a failure mode nobody has ever seen. It all looked thorough and relevant. It was also completely unasked for.
A week later I caught myself doing the same thing, just one layer down. I wasn’t adding features, I was adding tests. New edge cases for inputs the application will never receive. Additional coverage for code paths that existed only because I had generated the code in the first place. I told myself I was being thorough, but found I was going down that rabbit hole, because writing one more test case had stopped costing me anything.
AI didn’t invent scope creep. Developers have always been more than capable of gold-plating a feature nobody asked for. What AI changed is the price paid for the plating. The typing used to be the brake, even if nobody thought of it that way. Now the typing is nearly free and the brake is removed.
Possible Is Not the Same as Necessary
AI can generate almost anything you can describe. This is genuinely useful, but it’s also a trap. “The tool can build it” becomes the reason to build it, instead of “the business asked for it” or “this failure is likely enough to guard against.”
Every extra feature is something a teammate has to read and understand. Every extra config option is a setting someone eventually sets wrong. Every extra test is a test someone has to maintain when the code underneath it legitimately changes, and a false alarm when it breaks for no real reason.
None of that is free just because generating it was. All those extras increase the number of system behaviors a developer has to understand when something breaks, and they give the AI stack more irrelevant paths to chase during troubleshooting.
The Request Nobody Made
Not all of this comes from the tool. Part of a senior developer’s job has always been noticing the requirement that showed up without anyone attached to it.
The contact address book gets a county field, then a country field, for a company that has never shipped anything outside the state. Every table gets created date, created by, modified date, and modified by, because that is what tables have. Nobody asked for any of it. It arrived because someone was building the screen and it seemed like the sort of thing that should be there.
Sometimes that instinct is right. Audit fields are cheap when the table is created and expensive to backfill two years later when the business wants to know who changed the price. They earn their place the way logging does, by being the thing you need on the day something goes wrong. The county field is a different story.
The point is not that extra is always wrong. The point is that somebody should be able to say who wants it and what it’s for, and “it seemed like it should be there” is not an answer. If the client does in fact want it, it belongs in the requirements where it can be estimated and prioritized like everything else.
The Discipline Has Moved
The old discipline was about output. Can I build this? Do I know how? AI has mostly answered that question. The discipline that matters now is restraint. Should I build this? Does it map to an actual requirement? Does this test protect against a real risk, or one I imagined because I could?
This is a different skill than writing code, and it isn’t one AI can do for you. It doesn’t know your business requirements. It doesn’t know which failure modes happen at your facility and which ones are only theoretically possible. Only you know that, and the tool will build well past that line if you let it.
In the last post I said that if you can’t explain the code without asking AI, you don’t own it, you’re renting it. Code nobody asked for is the same problem from the other direction. You own it either way, and now there is more of it.
What Sufficient Actually Looks Like
Sufficient doesn’t mean sloppy or partially implemented or half-baked. It means built to the requirement that was actually given and tested to the risk that is actually there. If the application talks to a database, test what happens when the database is unavailable, because that really does happen. Don’t build a configurable retry strategy with five algorithms nobody asked for, because that doesn’t.
There is a floor, and it doesn’t move with the requirements. The floor includes logging you can troubleshoot from at 2:00 in the morning, validation on anything crossing a trust boundary, error handling on every external call, and credentials that stay out of the source. Those are rarely in a requirements document and they go in anyway, because their absence is what turns an ordinary failure into an outage.
That is the distinction the county field misses. The floor is what the system needs in order to be supportable. Everything above it needs somebody’s name attached. “Nobody asked for it” is a reason to cut a feature, not a reason to skip error handling.
Here’s the standard I’ve landed on. Before anything optional goes into a codebase, I ask whether I could explain to the person paying for it why it needs to exist. If the honest answer is “because the tool made it easy to add,” it doesn’t go in.
AI is a genuine force multiplier. It is not a substitute for judgment about what should get built. That judgment was always the job. It just got a lot cheaper to skip.