Less is More: Code Churn
A few things stood the test of time, in software engineering for me, and "less is more" is one of them.
When my younger self had to solve Project Euler problems, each program had a certain repetition. Some functions rewritten over and over, but not as a function per se. It was quite a copy paste of lines. When all the problems were solved, it made me wonder the code can be written again. The mathematica of it remained scattered across black boxes.
Then I entered the professional world and had to write software that lived with or without me. The distributed systems and autonomous in the wild made me rethink how a solution isn't built in isolation but is built over the top of other components.
Today, when you give me a simple problem, my instinct isn't to open an IDE and write python code. I'll try my best to avoid writing any piece of code, or even make the problem insignificant and make it disappear magically.
That's what experience teaches you - the best solution is often no code at all.
The new dev enthusiasm
AI code generation has this energy of a developer who just discovered they can write code and wants to show everyone. It's like that phase where you start running because everyone else is running, not because you know where you're going. You see others importing libraries, so you import ten. You see abstractions in codebases, so you create five layers of them.
There's something psychologically satisfying about seeing lots of code generated. It feels productive. Lines of code scrolling past, folders getting created, package.json growing longer. Progress! Look at all this progress!
But here's the illusion - activity isn't progress. Code isn't an asset, it's a liability. Every line you write (or AI writes for you) is a line you need to test, maintain, debug, and explain to the next person. You're not building something, you're creating obligations. The best code is the code you don't write. Second best is the code you delete.
It's like buying a Swiss Army knife when all you needed was a bottle opener. Sure, it has a bottle opener, but now you're also carrying around a saw, scissors, and a mysterious hook thing no one understands.
Tech debt
AI loves dependencies. Oh boy, does it love them.
Need to format a date? Here's moment.js (deprecated btw, but AI doesn't always know that). Want to make an HTTP request? Let's pull in axios, request, got, and node-fetch for good measure. Processing a simple array? Time for lodash, underscore, AND ramda.
Think about debt for a moment. Not all debt is bad. A home loan is good debt - you're betting on an appreciating asset. A personal loan for a vacation? That's different. You're paying interest on something that's already lost its value the moment you spent it.
Technical debt works the same way. Some dependencies are like home loans - they're investments. A well-maintained library that solves a genuinely complex problem? That's appreciating. It gets better over time, the community fixes bugs, adds features, maintains security.
But most AI-suggested dependencies are like personal loans. They solve a trivial problem you could've handled in ten lines. Now you're paying EMIs - updating them, dealing with breaking changes, patching security vulnerabilities, explaining to new team members why you needed a library to capitalize strings.
Each dependency is another EMI you're signing up for. Another thing to update. Another potential security vulnerability. Another breaking change waiting to happen. Another 50MB in your node_modules (looking at you, webpack).
The smart move? Pay your tech debt in small EMIs. Refactor incrementally. Replace that heavyweight dependency with vanilla code, one function at a time. And before you take on new debt, ask yourself - is this an appreciating asset or am I just financing a vacation?
good AI code
When I use AI now, I specifically ask for no external dependencies unless absolutely necessary, no "future-proofing" or abstractions we don't need today, and straightforward boring solutions. Code that looks like it was written by a senior dev on a Friday afternoon who just wants to go home.
Because that's what maintainable code looks like. Not clever. Not impressive. Just working and easy to understand.
But here's where it gets tricky - code reviews. We've built this whole machinery around reviewing code. Bots that check for style violations, complexity metrics, test coverage percentages. And you know what happens? Reviewers become blind to actual issues.
You're looking at a PR, and the bot says "line too long" and "missing docstring" and "complexity score 15/10". Your brain is occupied with these mechanical things. You miss the fact that the entire approach is wrong. You don't notice that this introduces a circular dependency. You overlook that the logic could be five lines instead of fifty.
It's like having a car inspection that only checks if your floor mats are clean while ignoring that your brakes don't work. The review process becomes noise, and signal gets lost.
The best code reviews I've seen are ones where someone says "why do we need this at all?" That's the review that matters. Not whether you used camelCase or snake_case.
Churn and the joy of deletion
Code churn - the amount of code that gets added and then removed or rewritten - is a real metric teams track. And AI is a churn machine.
It'll happily generate 500 lines that solve your problem, then when you ask it to fix a bug, it'll rewrite 300 of those lines. Ask for a feature? Another 400 lines, plus refactoring 200 existing ones. Before you know it, you've churned through thousands of lines of code for what could've been a 50-line solution.
But here's what nobody tells you - deleting code gives you the ultimate joy. That dopamine hit when you realize you can remove an entire file because it was solving a problem that didn't exist. When you delete a dependency and the app still works. When you inline a function and suddenly everything makes sense.
Good changes are small changes. A PR with +3 -7 lines is usually better than +300 -200. If you're rewriting massive chunks of code, you're probably solving the wrong problem. The goal isn't to churn code, it's to make the codebase smaller, simpler, easier to understand.
It's like rearranging furniture in your house every week. Sure, it's activity, but are you actually making progress? Or are you just tired from moving the couch around?
The real lesson
I'm not saying don't use AI for coding. I use it all the time, and it's genuinely helpful. But treat it like a tool, not an oracle. When AI gives you code, read it, understand it, simplify it, and delete half of it probably. Question every import. Ask "could this be simpler?" Better yet, ask "do we need this at all?"
The goal isn't to generate code. The goal is to solve problems. And sometimes the best solution is the one that barely looks like code at all.
Remember: in five years, you won't be proud of how much code you generated. You'll be proud of how little code you needed to solve the problem. Less is more. Especially when it comes to dependencies, abstractions, and lines of code that nobody asked for.
P.S: If your AI-generated code needs comments to explain what it does, that's usually a sign it could be simpler. Code should read like prose, not assembly instructions.
Drop me a message on twitter @acsrujan if you've got war stories about AI-generated code monsters. Would love to hear them.