Suggests and applies code refactoring improvements including complexity reduction, code smell removal, and pattern improvements based on static analysis
Analyzes code to identify refactoring opportunities and suggests improvements to reduce complexity, remove code smells, and enhance maintainability. Use it when code becomes hard to understand, before adding features, or to address technical debt.
/plugin marketplace add mei28/claude-code/plugin install mei28-refactor-refactor@mei28/claude-codeAnalyzes code to identify refactoring opportunities and suggests improvements to reduce complexity, remove code smells, and enhance maintainability. Provides actionable refactoring recommendations with before/after examples.
/refactor
/refactor src/services/orderService.ts
/refactor --suggest
/refactor --apply
Arguments (optional):
--suggest: Only show suggestions (no changes)--apply: Apply automatic refactoringsProblem: Too many decision points (if/else, switch, loops)
// ❌ Before: Complexity 15
function calculatePrice(item, user, promotion) {
let price = item.basePrice;
if (user.isPremium) {
if (user.loyaltyYears > 5) {
price *= 0.85;
} else if (user.loyaltyYears > 2) {
price *= 0.9;
} else {
price *= 0.95;
}
}
if (promotion) {
if (promotion.type === 'percentage') {
price *= (1 - promotion.value / 100);
} else if (promotion.type === 'fixed') {
price -= promotion.value;
} else if (promotion.type === 'bogo') {
if (item.quantity > 1) {
price = price * 0.5 * item.quantity;
}
}
}
if (item.category === 'electronics') {
if (item.warranty) {
price += 49.99;
}
}
return price;
}
// ✅ After: Complexity 4
function calculatePrice(item, user, promotion) {
let price = item.basePrice;
price = applyUserDiscount(price, user);
price = applyPromotion(price, promotion, item);
price = addWarranty(price, item);
return price;
}
function applyUserDiscount(price, user) {
if (!user.isPremium) return price;
const discounts = {
5: 0.85,
2: 0.9,
0: 0.95
};
const discount = Object.entries(discounts)
.find(([years]) => user.loyaltyYears >= Number(years))?.[1] ?? 1;
return price * discount;
}
function applyPromotion(price, promotion, item) {
if (!promotion) return price;
const strategies = {
percentage: (p, promo) => p * (1 - promo.value / 100),
fixed: (p, promo) => p - promo.value,
bogo: (p, promo, itm) => itm.quantity > 1 ? p * 0.5 * itm.quantity : p
};
return strategies[promotion.type]?.(price, promotion, item) ?? price;
}
function addWarranty(price, item) {
return item.category === 'electronics' && item.warranty
? price + 49.99
: price;
}
Benefits:
Problem: Long methods doing multiple things
# ❌ Before: 45 lines
def process_order(order_data):
# Validate order
if not order_data.get('customer_id'):
raise ValueError('Missing customer ID')
if not order_data.get('items'):
raise ValueError('No items in order')
for item in order_data['items']:
if item['quantity'] <= 0:
raise ValueError('Invalid quantity')
# Calculate totals
subtotal = 0
for item in order_data['items']:
subtotal += item['price'] * item['quantity']
tax = subtotal * 0.08
shipping = 0
if subtotal < 50:
shipping = 10
total = subtotal + tax + shipping
# Save to database
cursor = db.cursor()
cursor.execute(
'INSERT INTO orders (customer_id, total) VALUES (?, ?)',
(order_data['customer_id'], total)
)
order_id = cursor.lastrowid
for item in order_data['items']:
cursor.execute(
'INSERT INTO order_items (order_id, product_id, quantity) VALUES (?, ?, ?)',
(order_id, item['product_id'], item['quantity'])
)
db.commit()
return order_id
# ✅ After: Each function < 10 lines
def process_order(order_data):
validate_order(order_data)
totals = calculate_totals(order_data)
order_id = save_order(order_data, totals)
return order_id
def validate_order(order_data):
if not order_data.get('customer_id'):
raise ValueError('Missing customer ID')
if not order_data.get('items'):
raise ValueError('No items in order')
for item in order_data['items']:
if item['quantity'] <= 0:
raise ValueError('Invalid quantity')
def calculate_totals(order_data):
subtotal = sum(item['price'] * item['quantity'] for item in order_data['items'])
tax = subtotal * 0.08
shipping = 10 if subtotal < 50 else 0
return {'subtotal': subtotal, 'tax': tax, 'shipping': shipping, 'total': subtotal + tax + shipping}
def save_order(order_data, totals):
order_id = insert_order(order_data['customer_id'], totals['total'])
insert_order_items(order_id, order_data['items'])
db.commit()
return order_id
def insert_order(customer_id, total):
cursor = db.cursor()
cursor.execute('INSERT INTO orders (customer_id, total) VALUES (?, ?)', (customer_id, total))
return cursor.lastrowid
def insert_order_items(order_id, items):
cursor = db.cursor()
for item in items:
cursor.execute(
'INSERT INTO order_items (order_id, product_id, quantity) VALUES (?, ?, ?)',
(order_id, item['product_id'], item['quantity'])
)
Problem: Same logic repeated in multiple places
// ❌ Before: Duplicated validation
function createUser(userData) {
if (!userData.email || !/@/.test(userData.email)) {
throw new Error('Invalid email');
}
if (!userData.name || userData.name.length < 2) {
throw new Error('Invalid name');
}
// ... create user
}
function updateUser(userId, userData) {
if (!userData.email || !/@/.test(userData.email)) {
throw new Error('Invalid email');
}
if (!userData.name || userData.name.length < 2) {
throw new Error('Invalid name');
}
// ... update user
}
// ✅ After: Extracted validation
function validateUserData(userData) {
const validators = {
email: (email) => email && /@/.test(email),
name: (name) => name && name.length >= 2
};
for (const [field, validator] of Object.entries(validators)) {
if (!validator(userData[field])) {
throw new Error(`Invalid ${field}`);
}
}
}
function createUser(userData) {
validateUserData(userData);
// ... create user
}
function updateUser(userId, userData) {
validateUserData(userData);
// ... update user
}
Problem: Type checking with if/else or switch
// ❌ Before: Type checking
class PaymentProcessor {
public void processPayment(Payment payment) {
if (payment.getType().equals("CREDIT_CARD")) {
processCreditCard(payment);
} else if (payment.getType().equals("PAYPAL")) {
processPayPal(payment);
} else if (payment.getType().equals("BANK_TRANSFER")) {
processBankTransfer(payment);
}
}
}
// ✅ After: Polymorphism
interface Payment {
void process();
}
class CreditCardPayment implements Payment {
public void process() {
// Credit card specific logic
}
}
class PayPalPayment implements Payment {
public void process() {
// PayPal specific logic
}
}
class BankTransferPayment implements Payment {
public void process() {
// Bank transfer specific logic
}
}
class PaymentProcessor {
public void processPayment(Payment payment) {
payment.process();
}
}
Problem: Long parameter lists
// ❌ Before: 8 parameters
function createInvoice(
customerId: string,
customerName: string,
customerEmail: string,
items: Item[],
subtotal: number,
tax: number,
shipping: number,
discount: number
): Invoice {
// ...
}
// ✅ After: Parameter object
interface InvoiceData {
customer: {
id: string;
name: string;
email: string;
};
items: Item[];
amounts: {
subtotal: number;
tax: number;
shipping: number;
discount: number;
};
}
function createInvoice(data: InvoiceData): Invoice {
// ...
}
// Usage
createInvoice({
customer: { id: '123', name: 'John', email: 'john@example.com' },
items: [/* ... */],
amounts: { subtotal: 100, tax: 8, shipping: 10, discount: 5 }
});
# ❌ Before: Magic numbers
def calculate_shipping(weight):
if weight < 5:
return 10
elif weight < 20:
return 15
else:
return 25
# ✅ After: Named constants
LIGHT_WEIGHT_THRESHOLD = 5
MEDIUM_WEIGHT_THRESHOLD = 20
LIGHT_PACKAGE_COST = 10
MEDIUM_PACKAGE_COST = 15
HEAVY_PACKAGE_COST = 25
def calculate_shipping(weight):
if weight < LIGHT_WEIGHT_THRESHOLD:
return LIGHT_PACKAGE_COST
elif weight < MEDIUM_WEIGHT_THRESHOLD:
return MEDIUM_PACKAGE_COST
else:
return HEAVY_PACKAGE_COST
# Read file to refactor
Read src/services/orderService.ts
# Calculate metrics
- Cyclomatic complexity
- Function length
- Code duplication percentage
- Nesting depth
Create TodoWrite checklist:
## Refactoring Analysis
- [x] Read and analyze code
- [x] Identify refactoring opportunities (5 found)
- [ ] High complexity function (line 45-120)
- [ ] Duplicated validation logic (lines 30, 78, 145)
- [ ] Magic numbers (lines 55, 89, 92)
- [ ] Long parameter list (line 12)
- [ ] Nested conditions (lines 200-250)
For each issue:
Apply safe, automated refactorings:
Skip complex refactorings requiring human judgment.
# Refactoring Report
## Summary
**File**: `src/services/orderService.ts`
**Refactoring Opportunities**: 5
**Estimated Improvement**:
- Complexity: 45 → 18 (-60%)
- Maintainability Index: 52 → 78 (+50%)
- Test Coverage Potential: 45% → 85%
## Recommendations
### 🔴 HIGH PRIORITY
#### 1. Reduce Complexity in `processOrder` (Lines 45-120)
**Current Complexity**: 18 (High)
**Target Complexity**: < 10
**Problem**: Function has too many responsibilities and decision points
**Suggestion**: Extract Method + Strategy Pattern
[Before/After code examples as shown above]
**Benefits**:
- Easier to test (4 small functions vs 1 large function)
- Easier to extend (add new discount types)
- Easier to understand (each function has single purpose)
**Effort**: Medium (30-45 minutes)
---
#### 2. Remove Duplicated Validation (Lines 30, 78, 145)
**Duplication**: 15 lines repeated 3 times
**Suggestion**: Extract validation function
[Before/After code]
**Benefits**:
- DRY principle
- Single source of truth for validation rules
- Easier to maintain (change once, not three times)
**Effort**: Low (10-15 minutes)
---
### 🟡 MEDIUM PRIORITY
#### 3. Replace Magic Numbers (Lines 55, 89, 92)
**Suggestion**: Extract constants
[Before/After code]
**Benefits**:
- Self-documenting code
- Easy to modify thresholds
- Consistent values across codebase
**Effort**: Low (5 minutes)
---
#### 4. Simplify Parameter List (Line 12)
**Current**: 8 parameters
**Target**: 1-3 parameters
**Suggestion**: Introduce Parameter Object
[Before/After code]
**Benefits**:
- Easier to call function
- Easier to add new parameters
- More maintainable
**Effort**: Medium (20-30 minutes)
---
### ⚪ LOW PRIORITY
#### 5. Reduce Nesting Depth (Lines 200-250)
**Current Depth**: 5 levels
**Target Depth**: < 3 levels
**Suggestion**: Guard Clauses + Early Returns
**Effort**: Medium (25-35 minutes)
---
## Automated Refactorings Available
The following can be applied automatically with `--apply`:
- ✅ Extract constants for magic numbers
- ✅ Rename variables to follow conventions
- ✅ Format code (indentation, spacing)
- ✅ Remove unused imports
Would you like to apply these? Run: `/refactor --apply`
## Manual Refactorings Required
These require human judgment and testing:
- ⚠️ Extract methods (need to determine boundaries)
- ⚠️ Introduce polymorphism (need to understand business logic)
- ⚠️ Restructure classes (architectural decision)
## Next Steps
1. **Fix High Priority Issues**: Start with complexity reduction
2. **Write Tests**: Before refactoring, ensure test coverage
3. **Refactor Incrementally**: One issue at a time
4. **Run Tests**: After each refactoring
5. **Commit**: Small, focused commits per refactoring
**Recommended Order**:
---
**Generated by**: Claude Code - Refactor Plugin
**Timestamp**: 2026-01-03 21:15:00
/test-generator → Run tests → /refactor
Safety net ensures refactoring doesn't break functionality.
Research shows changes under 200 lines:
Track metrics:
Don't wait for problems:
/code-review → /refactor → /test-generator → /code-review
/refactor → /test-generator → [Implement feature]
Clean up before adding complexity.
/code-review first to identify what needs refactoring--suggest to learn refactoring patternsSources:
/refactorRealiza refatoração segura e gradual de código, avaliando quantitativamente a aderência aos princípios SOLID. Visualiza dívida técnica e clarifica as prioridades de melhoria.