You have 5,000 lines of legacy code. It works, but its a mess. Every time you touch it, something breaks. So you ask Claude/GPT to refactor it, it spits out a wall of changes, and suddenly youre debugging for three hours.
Heres the thing: AI is actually fantastic at refactoring. Youre just asking it wrong.
The Dangerous Approach (Don't Do This)
Pasting your entire module and asking "refactor this" doesn't work because:
- AI sees the whole context and tries to "improve" everything at once
- You get back code you don't fully understand
- One assumption in the AI's reasoning breaks your weird edge case
- You can't review changes incrementally
The Smart Approach: Bite-Sized, Testable Chunks
1. Extract One Responsibility at a Time
Instead of refactoring a 300-line class, ask AI to extract a single method:
I have this function that does X, Y, and Z.
Can you extract just the Z part into its own function with a clear interface?
Heres the code: [paste just that function]
Heres what Z needs to return: [be specific]
This gets you a focused suggestion you can:
- Review in under 2 minutes
- Write tests for immediately
- Roll back if it breaks anything
- Merge before moving to the next chunk
2. Give AI Your Test Cases
Before asking for a refactor, paste your existing tests:
Here are my current tests for this function: [paste tests]
I want to refactor the internals, but these tests must still pass.
Can you suggest changes that keep the same behavior?
AI will work backward from your test requirements. Its like pair programming with someone who actually respects the spec.
3. Specify the "Why" Behind Your Constraints
Dont just say "keep it fast." Explain:
This function is called 10,000 times per second in the hot path.
Currently its O(n) and we cant afford worse.
We can refactor the logic, but not the time complexity.
AI stops suggesting elegant solutions that destroy performance and focuses on the actual constraint.
4. Ask for a Diff, Not a Rewrite
Instead of:
"Refactor this to use modern patterns"
Try:
"Whats the minimum change needed to use dependency injection here?
Show me just the lines that change, and explain why each change is necessary."
You get surgical changes, not a complete rewrite.
5. Review With a Linter First
Before asking AI to refactor, run your code through a linter and ask AI to address only the lint errors:
My linter found these issues: [paste output]
Can you fix these specific items without changing behavior?
This gives you free refactoring thats guaranteed to improve code quality without introducing risk.
The Testing Pattern
After each AI-suggested refactor:
- Run your tests immediately — if they pass, youre good
- Check edge cases you know exist — does it handle null, empty arrays, the weird state your app gets into?
- Diff against the original — are there changes you didn't ask for? (Red flag.)
- Commit separately — one refactor per commit, so you can bisect if something breaks later
Real Example: Refactoring a Messy Handler
Instead of giving AI this:
async function handleUserUpdate(req, res) {
try {
const { id } = req.params;
const user = await User.findById(id);
if (!user) {
return res.status(404).json({ error: 'User not found' });
}
user.name = req.body.name;
user.email = req.body.email;
user.role = req.body.role;
user.updatedAt = new Date();
await user.save();
// ... 20 more lines
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
}
Ask for one thing:
"Extract validation logic into a separate function. This should check that email is unique and name/email are non-empty. Return an error object if validation fails, null if valid. Don't touch anything else."
Now you have:
function validateUserUpdate(data) {
const errors = {};
if (!data.name?.trim()) errors.name = 'Name required';
if (!data.email?.trim()) errors.email = 'Email required';
// ... etc
return Object.keys(errors).length ? errors : null;
}
Then extract the DB save logic, then the response formatting. Four commits, each one reviewable in 30 seconds.
When AI Refactoring Goes Wrong
If something breaks:
- You have a good bisect point — you know which commit broke it
- The change is small — you understand what went wrong
- You can fix it immediately — its usually a one-line revert + manual fix
If youd let AI rewrite the whole thing, debugging takes hours.
The Rule: Reversible Changes
Every refactoring should be:
- Reviewable in one sitting (if it takes >15 min to review, its too big)
- Testable immediately (you can run tests right now)
- Revertible in one command (git revert should work)
If your AI-suggested change doesn't meet these, ask AI to break it into smaller pieces.
Want to level up your dev skills faster? Check out the LearnAI Weekly newsletter for practical AI tips, no-code tools, and coding strategies delivered to your inbox.
This stuff works because AI is actually better at incremental improvement than humans are. We get attached to "the right way." AI just sees the code. Use that superpower wisely.
Top comments (0)