| name | refactor |
| description | Perform safe refactoring operations while preserving behavior and maintaining code integrity. Use when: renaming identifiers, extracting functions/modules, inlining code, moving files, or restructuring code without changing functionality. Do NOT use when: adding new features, fixing bugs (use standard editing), or making breaking API changes.
|
Refactor
Execute safe refactoring operations with verification at each step. Refactoring changes code structure without altering external behavior.
Core Principle
Preserve behavior. Every refactoring must pass tests before and after. If behavior changes, it's not refactoring—it's a rewrite.
Refactoring Operations
Rename
Rename variables, functions, classes, files, or directories while maintaining all references.
When to use:
- Identifier name is unclear or violates naming conventions
- Code review feedback on naming
- Aligning names with business domain
Steps:
- Find all occurrences (definitions + usages)
- Verify the scope (global vs local)
- Rename atomically (all at once)
- Run tests to confirm behavior unchanged
grep -r "oldName" --include="*.ts" --include="*.js" --include="*.py"
Extract
Pull out a code block into a new function, method, class, or module.
When to use:
- Function is too long (>30 lines)
- Code block is duplicated elsewhere
- Logic can be reused in other contexts
- Improving readability by naming complex operations
Steps:
- Identify the code block to extract
- Determine inputs (parameters) and outputs (return value)
- Create the new function/module
- Replace original code with a call to the new function
- Verify tests still pass
Extraction targets:
- Function/method extraction
- Class extraction
- Module/file extraction
- Interface/type extraction
Inline
Replace a function call with the function body.
When to use:
- Function is trivial (one-liner)
- Function is called only once
- Indirection adds unnecessary complexity
- Making code easier to follow
Steps:
- Verify the function has no side effects
- Copy function body to call site
- Replace arguments with actual values
- Remove the now-unused function
- Run tests
Move
Relocate code to a more appropriate location in the codebase.
When to use:
- Code belongs in a different module/package
- Organizing by feature instead of type
- Reducing coupling between modules
- Aligning with project architecture
Steps:
- Identify the target location
- Update all import paths
- Ensure no circular dependencies
- Move the file/code
- Update tests and documentation
Safety Checklist
Before any refactoring, verify:
git status
git stash
npm test 2>/dev/null || go test ./... 2>/dev/null || pytest 2>/dev/null || cargo test 2>/dev/null
git checkout -b refactor/<description>
Pre-refactoring checklist:
Step-by-Step Workflow
Phase 1: Preparation
-
Understand current behavior
- Read the code thoroughly
- Run existing tests
- Note edge cases and dependencies
-
Plan the refactoring
- Choose the operation type (rename/extract/inline/move)
- Identify all affected files
- Estimate risk level
-
Set up safety net
git checkout -b refactor/<description>
Phase 2: Execution
-
Make the change incrementally
- One logical change per commit
- Small, reviewable steps
- Never mix refactoring with feature changes
-
Verify after each step
npm test 2>/dev/null || go test ./...
npm run build 2>/dev/null || go build ./...
-
Commit frequently
git add -A
git commit -m "ref: <what changed>"
Phase 3: Verification
-
Run full test suite
npm test 2>/dev/null && npm run lint 2>/dev/null
-
Manual smoke test (if applicable)
- Start the application
- Verify critical paths work
- Check edge cases
-
Clean up
Common Patterns
Pattern: Extract Function
function processOrder(order: Order) {
}
function processOrder(order: Order) {
const validated = validateOrder(order);
const calculated = calculateTotals(validated);
return persistOrder(calculated);
}
Pattern: Move to Module
mkdir -p src/utils/validation
mkdir -p src/utils/formatting
mv src/utils/validateUser.js src/utils/validation/
mv src/utils/validateOrder.js src/utils/validation/
find . -name "*.ts" -exec sed -i 's|from.*utils/validateUser|from../utils/validation/validateUser|g' {} \;
Pattern: Rename with IDE Support
npx tsserver --rename <file> <oldName> <newName>
grep -rl "oldFunctionName" src/ | xargs sed -i 's/oldFunctionName/newFunctionName/g'
Edge Cases
Circular Dependencies
When moving code creates circular imports:
- Extract shared types/interfaces to a separate module
- Use dependency injection
- Create a facade module
Breaking Changes
If refactoring must change public API:
- Create new API alongside old
- Deprecate old API
- Migrate callers gradually
- Remove old API in future release
Large-Scale Refactoring
For codebase-wide changes:
- Script the change (sed, ast-grep, codemods)
- Run on entire codebase at once
- Commit as single atomic change
- Verify everything still works
Troubleshooting
Tests Fail After Refactoring
git diff HEAD~1
Build Errors
npx tsc --noEmit
goimports -l .
grep -r "oldName" --include="*.ts" --include="*.js" --include="*.go"
Performance Regression
Best Practices
- Small steps — One logical change per commit
- Tests first — Never refactor without passing tests
- Version control — Use branches for risky refactoring
- No behavior changes — Refactor only, then change behavior separately
- Document intent — Commit messages explain WHY, not WHAT
- Review carefully — Refactoring bugs are subtle
- Incremental rollout — For large changes, merge progressively