| name | refactoring-specialist |
| description | Code refactoring expert for improving code structure, readability, and maintainability. Use when user asks to refactor, clean up, or improve code quality. |
| allowed-tools | Read, Write, Edit, Bash, Grep, Glob |
| metadata | {"hooks":{"after_complete":[{"trigger":"self-improving-agent","mode":"background","reason":"Learn from refactoring patterns"},{"trigger":"session-logger","mode":"auto","reason":"Log refactoring activity"}]}} |
Refactoring Specialist
Expert guidance on refactoring code to improve structure, readability, and maintainability while preserving functionality.
When This Skill Activates
Activates when you:
- Ask to refactor code
- Request cleanup or improvement
- Mention "technical debt" or "code smell"
- Want to improve code quality
Refactoring Principles
- Preserve Behavior: Refactoring must not change external behavior
- Small Steps: Make small, incremental changes
- Test Coverage: Ensure tests pass before and after
- Commit Often: Commit after each successful refactoring
Code Smells to Address
1. Long Method
Symptom: Function > 20-30 lines
Refactoring: Extract Method
function processOrder(order) {
}
function processOrder(order) {
validateOrder(order);
calculateTotals(order);
saveOrder(order);
sendConfirmation(order);
}
2. Duplicate Code
Symptom: Similar code in multiple places
Refactoring: Extract Method / Template Method
class UserService {
async validateEmail(email) {
if (!email || !email.includes('@')) return false;
const domain = email.split('@')[1];
return domain.length > 0;
}
}
class AdminService {
async validateEmail(email) {
if (!email || !email.includes('@')) return false;
const domain = email.split('@')[1];
return domain.length > 0;
}
}
class EmailValidator {
async validate(email) {
if (!email || !email.includes('@')) return false;
return email.split('@')[1].length > 0;
}
}
3. Large Class
Symptom: Class doing too many things
Refactoring: Extract Class
class User {
}
class User { }
class UserAuth { }
class UserProfile { }
class UserNotifier { }
4. Long Parameter List
Symptom: Function with 4+ parameters
Refactoring: Introduce Parameter Object
function createUser(name, email, age, address, phone, role) { ... }
function createUser(user: UserData) { ... }
interface UserData {
name: string;
email: string;
age: number;
address: string;
phone: string;
role: string;
}
5. Feature Envy
Symptom: Method uses more data from other classes
Refactoring: Move Method
class Report {
formatSummary(formatter) {
const options = formatter.getFormattingOptions();
}
}
class Formatter {
formatReport(report) {
const discount = this.discountLevel;
}
}
6. Data Clumps
Symptom: Same data appearing together
Refactoring: Extract Value Object
function drawShape(x, y, width, height) { ... }
function moveShape(x, y, width, height, dx, dy) { ... }
class Rectangle {
constructor(x, y, width, height) { ... }
}
function drawShape(rect: Rectangle) { ... }
7. Primitive Obsession
Symptom: Using primitives instead of small objects
Refactoring: Replace Primitive with Object
function createUser(name, email, phone) { ... }
class Email {
constructor(value) {
if (!this.isValid(value)) throw new Error('Invalid email');
this.value = value;
}
}
8. Switch Statements
Symptom: Large switch on type
Refactoring: Replace Conditional with Polymorphism
function calculatePay(employee) {
switch (employee.type) {
case 'engineer': return employee.salary * 1.2;
case 'manager': return employee.salary * 1.5;
case 'sales': return employee.salary * 1.1;
}
}
interface Employee {
calculatePay(): number;
}
class Engineer implements Employee {
calculatePay() { return this.salary * 1.2; }
}
9. Temporary Field
Symptom: Variables only used in certain scenarios
Refactoring: Extract Class
class User {
calculateRefund() {
this.tempRefundAmount = 0;
return this.tempRefundAmount;
}
}
class RefundCalculator {
calculate(user) {
}
}
10. Comments
Symptom: Code needs extensive comments
Refactoring: Extract Method with clear name
function calc(u, i) {
let t = 0;
if (u.vip) t *= 0.9;
if (u.state === 'CA') t *= 1.08;
return t;
}
function calculateTotalPrice(user: User, items: Item[]): number {
let total = items.sum(i => i.price);
if (user.isVIP) {
total = applyVIPDiscount(total);
}
return applyTax(total, user.state);
}
Refactoring Steps
- Identify the smell - What makes this code hard to work with?
- Determine the refactoring - Which technique applies?
- Ensure tests pass - Green before starting
- Apply the refactoring - Make the change
- Run tests - Verify behavior unchanged
- Commit - Small, atomic commits
Safe Refactoring Practices
- Use your IDE's refactoring tools (Rename, Extract, Move)
- Run tests frequently (after each change)
- Keep commits small and focused
- Write a descriptive commit message
- Consider code reviews for complex refactorings
Before Refactoring
After Refactoring
References
references/smells.md - Complete code smell catalog
references/techniques.md - Refactoring techniques
references/checklist.md - Refactoring checklist