The death of clean code: How AI ended our obsession with perfection
Clean Code served us well. But it’s time to move on. In the LLM era, messy code that ships fast beats elegant code that ships late.
The sacred cow we need to slaughter
For two decades, “Clean Code” has been the engineering bible. We’ve obsessed over perfect abstractions, elegant patterns, and code that reads like poetry. We’ve spent hours debating naming conventions, refactoring for purity, and achieving that mythical 100% test coverage.
Here’s the uncomfortable truth: your users don’t care.
They don’t care if your code is clean. They don’t care about your SOLID principles. They don’t care if you used dependency injection or if your functions are under 20 lines.
They care if your product works. If it delights them. If it solves their problems.
And now, with LLMs, we can finally optimize for what actually matters.
The old religion
Clean Code made sense in its time. When humans were the bottleneck, when every line needed to be understood and maintained by other humans, when refactoring was expensive and bugs were hard to find.
We built cathedrals of code. Beautiful, elegant, pristine. We’d spend days crafting the perfect abstraction, weeks refactoring for cleanliness, months building frameworks for problems we might have someday.
Meanwhile, our users waited. Features shipped slowly. Bugs lingered while we debated architecture. We prioritized code quality over product quality, telling ourselves they were the same thing.
They’re not.
Enter the LLMs
Here’s what changes everything: LLMs don’t care about your code quality either.
They don’t get confused by long functions. They don’t mind repetition. They’re not impressed by your clever abstractions. They just need clarity and context.
Suddenly, the cost of “messy” code plummets. That spaghetti function you were going to spend a day refactoring? An LLM can understand it, modify it, and test it in minutes. That repeated code across five files? The LLM will update all instances flawlessly.
The bottleneck has shifted. It’s no longer “how maintainable is this code?” It’s “how fast can we ship value to users?”
The new religion: Great products
In the age of AI-assisted development, we optimize for different things:
Ship speed over code elegance: That feature your users are begging for? Ship it today with “messy” code rather than next week with “clean” code.
Documentation over abstraction: Instead of clever patterns that self-document, write explicit docs everywhere. LLMs will keep them updated.
Redundancy over DRY: Repeat yourself. It’s fine. LLMs don’t get bored updating multiple places.
Explicit over implicit: That “elegant” implicit behavior? Make it boringly explicit. LLMs need clarity, not cleverness.
Product metrics over code metrics: Stop measuring test coverage. Start measuring user satisfaction.
What this actually looks like
Let me be concrete. Here’s code from our production system:
// Old way: “Clean”
class EmailService extends AbstractMessageService {
constructor(provider: IEmailProvider) {
super(provider);
}
async send(message: Message): Promise<void> {
return this.provider.dispatch(message);
}
}
// New way: “Great Product”
async function sendEmail(to, subject, body) {
// This function sends emails. It’s used by:
// - Password reset flow
// - User notifications
// - Admin alerts
console.log(`Sending email to ${to}`);
if (!to || !subject || !body) {
throw new Error(’Missing required fields: to, subject, and body are all required’);
}
try {
await gmail.send({ to, subject, body });
console.log(’Email sent successfully’);
} catch (error) {
console.error(’Failed to send email:’, error);
// Try backup provider
await sendgrid.send({ to, subject, body });
}
}
The second version would make Clean Code advocates weep. It’s longer, has console.logs, mixes concerns, has no abstraction. It’s also:
Instantly understandable
Debuggable without diving through inheritance chains
Modifiable by any LLM without context about our architecture
Shipping value while the first version is still being architected
Follow Neople for more heretical takes on building great products that users actually care about.
The liberation
Letting go of Clean Code is liberating. Instead of agonizing over the perfect design pattern, I’m shipping features. Instead of refactoring for elegance, I’m fixing user-reported bugs. Instead of writing clever code, I’m writing clear code.
My code is messier. It has more documentation than logic. There’s redundancy everywhere. Console.logs litter the codebase. Functions are too long. Files are poorly organized.
And our product has never been better.
User satisfaction is up. Feature velocity has 10x’d. Bugs get fixed in hours, not weeks. We ship experiments daily instead of quarterly.
The heresy that’s actually wisdom
This is heresy in traditional software circles. I’m advocating for what we’ve been taught to avoid: messy code, poor abstractions, violated principles.
But principles are means, not ends. The end is great products that delight users. If messy code gets us there faster in the age of LLMs, then messy code is the right choice.
Your users don’t open your codebase. They open your product. Optimize accordingly.
The new principles
If Clean Code had its principles (DRY, SOLID, etc.), Great Product development has its own:
User value over code quality: Every decision should prioritize user impact
Clarity over cleverness: LLMs need to understand your intent instantly
Speed over perfection: Ship today, iterate tomorrow
Documentation over abstraction: Explain everything, assume nothing
Product metrics over code metrics: Measure what matters to users
The future is already here
This isn’t theoretical. Teams using LLMs are already making this shift, whether they admit it or not. They’re shipping faster with “worse” code and better products.
The old guard will resist. They’ll point to technical debt, maintenance nightmares, and the collapse of software craftsmanship. They’re fighting the last war.
In the new world, technical debt is paid by LLMs in milliseconds. Maintenance is a conversation with an AI. Craftsmanship means crafting great products, not great code.
Your choice
You can stick to Clean Code. You can keep crafting perfect abstractions while your competitors ship features. You can maintain your principles while your users switch to products that actually solve their problems.
Or you can embrace the new reality. Write messier code. Ship faster. Focus on product quality over code quality. Let LLMs handle the maintenance burden while you handle the user delight burden.
From Clean Code to great products. Your users are waiting.
Building great products with messy code at neople.io. Our users don’t care about our code quality. They care that we ship what they need, when they need it.


