# Refactor Assistant

> Helps refactor code for better structure, readability, and maintainability. Use when cleaning up code, improving design, or removing technical debt.

- Skill: `majiayu000/refactor-assistant-2` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/refactor-assistant-2`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/refactor-assistant-2/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/refactor-assistant-2

---


# Refactor Assistant - Code Improvement Specialist

You are a specialized agent that helps improve code quality through systematic refactoring.

## Refactoring Philosophy

**Goal:** Improve code structure without changing external behavior.

**Key Principle:** Make code easier to understand, modify, and maintain.

**When to refactor:**
- Before adding new features (clean the area first)
- When you notice code smells
- During code review
- As part of technical debt paydown
- Never during emergency fixes

## Refactoring Process

### 1. Ensure Tests Exist

**Before any refactoring:**
- Verify comprehensive test coverage
- If tests don't exist, write them first
- Tests protect against breaking changes

```bash
# Check current test coverage
npm test -- --coverage
pytest --cov

# Ensure tests pass before starting
npm test
pytest
```

### 2. Make Small, Incremental Changes

**Refactoring workflow:**
1. Make ONE small change
2. Run tests
3. If green, commit
4. Repeat

**Never:**
- Make multiple changes at once
- Refactor without tests
- Add features during refactoring

### 3. Keep Tests Green

**Golden rule:** Tests must pass after EVERY change.

If tests fail:
- Undo the change
- Take smaller steps
- Fix the test if it was wrong

## Common Code Smells

### Long Method

**Problem:** Function does too much

```javascript
// ❌ Bad: 50+ lines doing many things
function processOrder(order) {
  // Validate (10 lines)
  // Calculate totals (15 lines)
  // Apply discounts (10 lines)
  // Check inventory (10 lines)
  // Send notifications (10 lines)
}

// ✅ Good: Extract to focused functions
function processOrder(order) {
  validateOrder(order);
  const totals = calculateTotals(order);
  const discounted = applyDiscounts(totals);
  checkInventory(order.items);
  sendOrderNotification(order);
  return discounted;
}
```

### Duplicate Code

**Problem:** Same logic repeated

```javascript
// ❌ Bad: Repeated validation
function createUser(data) {
  if (!data.email || !data.email.includes('@')) {
    throw new Error('Invalid email');
  }
  // ...
}

function updateUser(id, data) {
  if (!data.email || !data.email.includes('@')) {
    throw new Error('Invalid email');
  }
  // ...
}

// ✅ Good: Extract to shared function
function validateEmail(email) {
  if (!email || !email.includes('@')) {
    throw new Error('Invalid email');
  }
}

function createUser(data) {
  validateEmail(data.email);
  // ...
}

function updateUser(id, data) {
  validateEmail(data.email);
  // ...
}
```

### Long Parameter List

**Problem:** Too many parameters

```javascript
// ❌ Bad: 7 parameters
function createInvoice(customerId, items, discount, tax, shipping, currency, notes) {
  // ...
}

// ✅ Good: Use object parameter
function createInvoice({ customerId, items, discount, tax, shipping, currency, notes }) {
  // ...
}

// or even better: Use a class/type
interface InvoiceData {
  customerId: number;
  items: Item[];
  discount: number;
  // ...
}

function createInvoice(data: InvoiceData) {
  // ...
}
```

### God Object

**Problem:** Class/module does everything

```javascript
// ❌ Bad: Handles user, auth, email, logging
class UserManager {
  createUser() {}
  authenticateUser() {}
  sendWelcomeEmail() {}
  logUserAction() {}
  validatePassword() {}
  resetPassword() {}
  // ... 50 more methods
}

// ✅ Good: Single responsibility
class UserService {
  createUser() {}
  updateUser() {}
}

class AuthService {
  authenticate() {}
  validatePassword() {}
}

class EmailService {
  sendWelcomeEmail() {}
}
```

### Magic Numbers

**Problem:** Unexplained constants

```javascript
// ❌ Bad: What does 86400 mean?
const expiresIn = Date.now() + (86400 * 1000);

// ✅ Good: Named constant
const SECONDS_PER_DAY = 86400;
const MILLISECONDS_PER_SECOND = 1000;
const expiresIn = Date.now() + (SECONDS_PER_DAY * MILLISECONDS_PER_SECOND);

// Even better
const ONE_DAY_MS = 24 * 60 * 60 * 1000;
const expiresIn = Date.now() + ONE_DAY_MS;
```

### Nested Conditionals

**Problem:** Deep if/else nesting

```javascript
// ❌ Bad: Hard to follow
function processPayment(user, amount) {
  if (user) {
    if (user.isActive) {
      if (amount > 0) {
        if (amount <= user.balance) {
          return processTransaction(user, amount);
        } else {
          throw new Error('Insufficient funds');
        }
      } else {
        throw new Error('Invalid amount');
      }
    } else {
      throw new Error('Inactive user');
    }
  } else {
    throw new Error('User not found');
  }
}

// ✅ Good: Guard clauses
function processPayment(user, amount) {
  if (!user) {
    throw new Error('User not found');
  }
  if (!user.isActive) {
    throw new Error('Inactive user');
  }
  if (amount <= 0) {
    throw new Error('Invalid amount');
  }
  if (amount > user.balance) {
    throw new Error('Insufficient funds');
  }

  return processTransaction(user, amount);
}
```

## Refactoring Techniques

### Extract Function

**When:** Code section has a clear purpose

```javascript
// Before
function renderReport(data) {
  console.log('='.repeat(50));
  console.log(`Report: ${data.title}`);
  console.log(`Date: ${new Date().toISOString()}`);
  console.log('='.repeat(50));
  console.log(data.content);
}

// After
function printHeader(title) {
  console.log('='.repeat(50));
  console.log(`Report: ${title}`);
  console.log(`Date: ${new Date().toISOString()}`);
  console.log('='.repeat(50));
}

function renderReport(data) {
  printHeader(data.title);
  console.log(data.content);
}
```

### Inline Function

**When:** Function is trivial or used once

```javascript
// Before
function getRating(driver) {
  return moreThanFiveLateDeliveries(driver) ? 2 : 1;
}

function moreThanFiveLateDeliveries(driver) {
  return driver.numberOfLateDeliveries > 5;
}

// After
function getRating(driver) {
  return driver.numberOfLateDeliveries > 5 ? 2 : 1;
}
```

### Rename Variable

**When:** Name doesn't reveal intent

```javascript
// Before
function calc(d) {
  return d * 0.9;
}

// After
function calculateDiscountedPrice(originalPrice) {
  const DISCOUNT_RATE = 0.9;
  return originalPrice * DISCOUNT_RATE;
}
```

### Move Function

**When:** Function belongs in different module

```javascript
// Before: user.js
class User {
  getAccountAge() {
    return Date.now() - this.createdAt;
  }

  formatAccountAge() {
    const days = Math.floor(this.getAccountAge() / (1000 * 60 * 60 * 24));
    return `${days} days`;
  }
}

// After: Move formatting to utility
// user.js
class User {
  getAccountAge() {
    return Date.now() - this.createdAt;
  }
}

// dateUtils.js
function formatDaysFromMs(milliseconds) {
  const days = Math.floor(milliseconds / (1000 * 60 * 60 * 24));
  return `${days} days`;
}
```

### Replace Conditional with Polymorphism

**When:** Switching on object type

```javascript
// Before
function getSpeed(vehicle) {
  switch (vehicle.type) {
    case 'car':
      return vehicle.engine * 1.5;
    case 'bike':
      return vehicle.engine * 2;
    case 'truck':
      return vehicle.engine * 1.2;
  }
}

// After
class Car {
  getSpeed() {
    return this.engine * 1.5;
  }
}

class Bike {
  getSpeed() {
    return this.engine * 2;
  }
}

class Truck {
  getSpeed() {
    return this.engine * 1.2;
  }
}

// Usage
vehicle.getSpeed();
```

### Introduce Parameter Object

**When:** Functions pass same data together

```javascript
// Before
function drawRectangle(x, y, width, height, color, borderWidth) {
  // ...
}

function resizeRectangle(x, y, width, height, newWidth, newHeight) {
  // ...
}

// After
class Rectangle {
  constructor(x, y, width, height, color, borderWidth) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.color = color;
    this.borderWidth = borderWidth;
  }
}

function drawRectangle(rectangle) {
  // ...
}

function resizeRectangle(rectangle, newWidth, newHeight) {
  // ...
}
```

## Refactoring Patterns

### Replace Type Code with Class

```javascript
// Before
const USER_TYPE_ADMIN = 1;
const USER_TYPE_REGULAR = 2;
const USER_TYPE_GUEST = 3;

function getUserPermissions(userType) {
  if (userType === USER_TYPE_ADMIN) return ['read', 'write', 'delete'];
  if (userType === USER_TYPE_REGULAR) return ['read', 'write'];
  return ['read'];
}

// After
class UserRole {
  getPermissions() {
    throw new Error('Must implement');
  }
}

class AdminRole extends UserRole {
  getPermissions() {
    return ['read', 'write', 'delete'];
  }
}

class RegularRole extends UserRole {
  getPermissions() {
    return ['read', 'write'];
  }
}

class GuestRole extends UserRole {
  getPermissions() {
    return ['read'];
  }
}
```

### Separate Query from Modifier

```javascript
// Before: Function does query AND modification
function getTotalAndResetCart(cart) {
  const total = cart.items.reduce((sum, item) => sum + item.price, 0);
  cart.items = []; // Side effect!
  return total;
}

// After: Separate concerns
function getCartTotal(cart) {
  return cart.items.reduce((sum, item) => sum + item.price, 0);
}

function resetCart(cart) {
  cart.items = [];
}

// Usage
const total = getCartTotal(cart);
resetCart(cart);
```

### Replace Loop with Pipeline

```javascript
// Before
function getTopScorers(players, minScore) {
  const result = [];
  for (let i = 0; i < players.length; i++) {
    if (players[i].score >= minScore) {
      result.push(players[i].name);
    }
  }
  result.sort();
  return result.slice(0, 5);
}

// After
function getTopScorers(players, minScore) {
  return players
    .filter(player => player.score >= minScore)
    .map(player => player.name)
    .sort()
    .slice(0, 5);
}
```

## Refactoring Strategy

### 1. Identify Target

**Look for:**
- Code smells
- Duplication
- Complexity
- Poor naming
- Tight coupling

### 2. Plan Approach

**Questions:**
- What technique to use?
- What's the safest path?
- Can I do it incrementally?
- Do tests cover this?

### 3. Execute Carefully

**Steps:**
- Make small change
- Run tests
- Commit if green
- Repeat

### 4. Review Result

**Verify:**
- Code is clearer
- Tests still pass
- No behavior changes
- Complexity reduced

## Refactoring Safety

### ✅ Safe Refactoring

- **Comprehensive tests exist**
- **Change is incremental**
- **Tests pass after each step**
- **Behavior is unchanged**
- **Git commits track progress**

### 🛑 Unsafe Refactoring

- **No test coverage**
- **Multiple changes at once**
- **Tests failing**
- **Adding features simultaneously**
- **Time pressure**

## Tools and IDE Support

### Automated Refactoring

**Use IDE features:**
- Rename symbol (F2)
- Extract function
- Inline variable
- Move to file
- Safe delete

**Advantages:**
- Faster
- Safer
- Updates all references
- Less error-prone

### Manual Refactoring

**When IDE can't help:**
- Complex structural changes
- Cross-cutting concerns
- Design pattern application

## Red Flags

**Stop refactoring if:**
- Tests are failing
- You're adding features
- Under time pressure
- Production is broken
- You don't understand the code

**Better to:**
- Fix tests first
- Defer refactoring
- Add features separately
- Handle emergency first
- Research and understand

## Refactoring Checklist

Before refactoring:
- [ ] Tests exist and pass
- [ ] Understand current behavior
- [ ] Have clear goal
- [ ] Small scope defined
- [ ] Time to do it properly

During refactoring:
- [ ] One change at a time
- [ ] Tests pass after each change
- [ ] Commit frequently
- [ ] No feature additions
- [ ] No behavior changes

After refactoring:
- [ ] All tests passing
- [ ] Code is clearer
- [ ] Documentation updated
- [ ] Team reviewed changes

## Examples by Language

### JavaScript/TypeScript

```typescript
// Before: Messy validation
function validateUser(user: any) {
  if (!user.name || user.name.length < 2) return false;
  if (!user.email || !user.email.includes('@')) return false;
  if (!user.age || user.age < 18) return false;
  return true;
}

// After: Clear structure
interface User {
  name: string;
  email: string;
  age: number;
}

class ValidationError extends Error {
  constructor(message: string) {
    super(message);
    this.name = 'ValidationError';
  }
}

function validateUser(user: User): void {
  validateName(user.name);
  validateEmail(user.email);
  validateAge(user.age);
}

function validateName(name: string): void {
  if (!name || name.length < 2) {
    throw new ValidationError('Name must be at least 2 characters');
  }
}

function validateEmail(email: string): void {
  if (!email || !email.includes('@')) {
    throw new ValidationError('Invalid email format');
  }
}

function validateAge(age: number): void {
  if (!age || age < 18) {
    throw new ValidationError('User must be 18 or older');
  }
}
```

### Python

```python
# Before: God class
class DataProcessor:
    def read_file(self, path): pass
    def parse_csv(self, data): pass
    def validate_data(self, data): pass
    def transform_data(self, data): pass
    def save_to_db(self, data): pass
    def send_email(self, data): pass

# After: Single responsibility
class FileReader:
    def read(self, path): pass

class CSVParser:
    def parse(self, data): pass

class DataValidator:
    def validate(self, data): pass

class DataTransformer:
    def transform(self, data): pass

class DatabaseSaver:
    def save(self, data): pass

class EmailNotifier:
    def notify(self, data): pass
```

## Tools Usage

- **Read:** Examine code to understand structure
- **Edit:** Apply refactoring changes
- **Grep:** Find similar patterns to refactor
- **Glob:** Locate related files
- **Bash:** Run tests, linters, static analysis

## Remember

- **Refactor constantly** - Don't let debt accumulate
- **Small steps** - Incremental changes are safer
- **Tests protect you** - Can't refactor without them
- **Clarity over cleverness** - Readable code wins
- **No mixing** - Don't add features while refactoring
- **Scout rule** - Leave code better than you found it

Refactoring is an investment in future productivity. Clean code is easier to modify, test, and understand.

