Tutorial 5: Use AI for Refactoring
- Contributor
- 4 days ago
- 2 min read
AI excels at mechanical transformations. Mass renames, pattern changes, language ports. Mechanical bug-fixes too.
Step 1: Identify Mechanical Refactors (10 min)
Good AI refactors:
Rename a function across many files
Update pattern (callbacks → promises → async)
Add types to JS
Change library (requests → httpx)
Restructure tests
Format / lint en masse
Bad AI refactors:
"Make the code better"
Restructure architecture
Break complex feature into modules
High-risk security-sensitive changes
Mechanical = AI strong. Subjective = AI weak.
Step 2: One-File Refactor (10 min)
Open the file. Prompt:
"Refactor this to use async/await instead of callbacks. Keep
behavior identical. Add JSDoc types."
AI generates. You diff. Apply if good.
Verify with tests.
Step 3: Multi-File Refactor (15 min)
For changes across many files:
Cursor's "Composer" / "Edit" modes
Claude Code's agent
Aider with --auto-commits
"Across this codebase, replace usage of the deprecated `oldFunc`
with `newFunc`. Behavior is identical but the signature changed:
oldFunc(a, b) → newFunc({a, b})"
Tool finds usages; rewrites. You review each change.
For 50+ files: faster than sed. Smarter than sed.
Step 4: Verify by Tests (10 min)
After refactor:
npm test
Tests catch regressions.
If tests are sparse: write more tests before refactoring. Tests are your safety net.
Step 5: Codemod Style (10 min)
For specific syntax transforms: AST-aware tools beat AI:
jscodeshift (JS)
ast-grep (multi-language)
libCST (Python)
These are deterministic. AI is probabilistic.
For high-risk mechanical refactors: AST tools. For one-offs: AI.
Step 6: Reset Your Branch (10 min)
Before mass refactor:
git checkout -b refactor-promises-to-async
After AI refactor:
git status # see all changes
git diff # review
If wrong:
git checkout -- . # reset
Branch + diff is your safety. Mass changes need easy revert.
Step 7: Commit Logically (10 min)
Don't commit a 500-file refactor as one commit.
Split:
git add src/auth/*
git commit -m "refactor(auth): callbacks to async/await"
git add src/users/*
git commit -m "refactor(users): same transform"
Easier to review. Easier to bisect later.
Step 8: Watch for Subtle Differences (15 min)
AI refactors sometimes:
Swap argument order
Change error handling slightly
Lose comments
Reformat unrelated lines
Diff carefully. Especially: behavior changes hidden in syntactic noise.
For high-stakes refactor: pair-review the diff with a teammate.
Step 9: Add Tests First (10 min)
Before mechanical refactor:
# Pin behavior with tests
npm test -- --coverage
If coverage is low: write tests for the area you'll refactor.
Tests are the contract. Refactor preserves the contract.
Step 10: Don't Refactor Just Because AI Could (5 min)
AI makes refactor cheap. Tempting: refactor everything.
But:
Each refactor = risk
Each refactor = team disruption
Each refactor = git history complexity
Refactor for a reason:
Removing tech debt
Enabling new features
Performance fix
Maintainability
Not "because we can."
What You Just Did
AI refactoring: identify mechanical, one-file, multi-file, verify, codemods, branch+diff, logical commits, watch differences, tests first, refactor for a reason. Productive use.
Common Failure Modes
Refactor without tests. Hidden behavior change ships.
Mass commit; impossible to review. Bugs slip.
Accept AI changes blindly. Subtle bugs.
Refactor every codebase weekly. Disruption > value.
Use AI where AST tools are deterministic. Probabilistic mistakes.


