# Refactoring Patterns

> Safe refactoring techniques — extract method, rename, move, inline, and structural patterns. Includes code smell identification and transformation recipes. Use when refactoring code or improving structure.

- **Type:** Skill
- **Install:** `agentstack add skill-claude-code-community-ireland-claude-code-resources-refactoring-patterns`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [Claude-Code-Community-Ireland](https://agentstack.voostack.com/s/claude-code-community-ireland)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [Claude-Code-Community-Ireland](https://github.com/Claude-Code-Community-Ireland)
- **Source:** https://github.com/Claude-Code-Community-Ireland/claude-code-resources/tree/main/plugins/vibeworks-library/skills/refactoring-patterns

## Install

```sh
agentstack add skill-claude-code-community-ireland-claude-code-resources-refactoring-patterns
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Refactoring Patterns

## Safety Rules

Before any refactoring, verify all of the following:

- [ ] Tests exist covering the code you will change
- [ ] All tests pass before you start
- [ ] Perform one transformation at a time
- [ ] Run tests after every single transformation
- [ ] Commit after each successful step
- [ ] Name every transformation in your commit message (e.g., "refactor: Extract Method -- validateEmail")
- [ ] Never change behavior and structure in the same commit
- [ ] If a step breaks tests, revert immediately and try a smaller step

## Code Smell Catalog

| Smell                  | Symptoms                                                   | Typical Refactoring                          |
|------------------------|------------------------------------------------------------|----------------------------------------------|
| Long Method            | Method over 20 lines; multiple levels of abstraction       | Extract Method                               |
| Large Class            | Class over 300 lines; too many responsibilities            | Extract Class                                |
| Feature Envy           | Method uses more data from another class than its own      | Move Method                                  |
| Data Clump             | Same group of fields/params appear together repeatedly     | Introduce Parameter Object                   |
| Primitive Obsession    | Using primitives instead of small domain objects           | Replace Primitive with Value Object          |
| Shotgun Surgery        | One change requires edits across many files                | Move Method, Inline Class                    |
| Divergent Change       | One class changed for many different reasons               | Extract Class                                |
| Dead Code              | Unreachable code, unused variables, commented-out blocks   | Remove Dead Code                             |
| Long Parameter List    | Method takes more than 3 parameters                        | Introduce Parameter Object                   |
| Switch Statements      | Repeated switch/if-else on the same type field             | Replace Conditional with Polymorphism        |
| Duplicate Code         | Same logic in multiple places                              | Extract Method, Extract Superclass           |
| Magic Numbers          | Unexplained literal values in logic                        | Replace Magic Number with Named Constant     |

### Smell Examples

**Long Method:**
```typescript
function processOrder(order: Order) {
  // validate (10 lines) + calculate totals (15 lines)
  // apply discounts (12 lines) + check inventory (8 lines)
  // create invoice (10 lines) + send notification (6 lines)
}
```

**Feature Envy:**
```typescript
class Order {
  calculateShipping() {
    if (this.customer.address.country === "US") {
      if (this.customer.tier === "premium") return 0;
      return this.customer.address.isRemote ? 15 : 5;
    }
    return 25;
  }
}
```

**Data Clump:**
```typescript
function createUser(name: string, street: string, city: string, state: string, zip: string) {}
function updateAddress(street: string, city: string, state: string, zip: string) {}
```

## Named Refactorings

| Refactoring                               | Input                             | Output                                 |
|-------------------------------------------|-----------------------------------|----------------------------------------|
| Extract Method                            | Code block inside a method        | New method + call site                 |
| Extract Class                             | Fields and methods from a class   | New class with focused responsibility  |
| Inline Method                             | Trivial method                    | Body placed at all call sites          |
| Rename                                    | Unclear name                      | Intention-revealing name               |
| Move Method                               | Method in wrong class             | Method in the class that owns the data |
| Introduce Parameter Object                | Multiple related parameters       | Single object parameter                |
| Replace Conditional with Polymorphism     | Type-based switch/if-else         | Subclasses with overridden method      |
| Replace Magic Number with Named Constant  | Literal number in code            | Named constant                         |
| Decompose Conditional                     | Complex boolean expression        | Named methods for conditions           |
| Remove Dead Code                          | Unused code                       | Deletion                               |

### Extract Method

**Recipe:** (1) Identify code to extract. (2) Create method with intention-revealing name. (3) Copy code in. (4) Local variables become locals; outer scope reads become parameters; modified-and-used-after become return values. (5) Replace original with call. (6) Run tests.

```typescript
// Before
function printInvoice(invoice: Invoice) {
  console.log("=== Invoice ===");
  let total = 0;
  for (const item of invoice.items) { total += item.price * item.quantity; }
  const tax = total * 0.08;
  console.log(`Total: ${total + tax}`);
}

// After
function printInvoice(invoice: Invoice) {
  console.log("=== Invoice ===");
  console.log(`Total: ${calculateGrandTotal(invoice.items)}`);
}

function calculateGrandTotal(items: InvoiceItem[]): number {
  const subtotal = items.reduce((sum, i) => sum + i.price * i.quantity, 0);
  return subtotal + subtotal * 0.08;
}
```

### Extract Class

**Recipe:** (1) Identify cohesive fields and methods. (2) Create new class. (3) Move fields. (4) Move methods. (5) Delegate from original. (6) Run tests after each move.

```typescript
// Before
class User {
  name: string; email: string;
  street: string; city: string; state: string; zip: string;
  fullAddress(): string { return `${this.street}, ${this.city}, ${this.state} ${this.zip}`; }
}

// After
class Address {
  constructor(public street: string, public city: string, public state: string, public zip: string) {}
  full(): string { return `${this.street}, ${this.city}, ${this.state} ${this.zip}`; }
}

class User {
  name: string; email: string; address: Address;
}
```

### Introduce Parameter Object

**Recipe:** (1) Create type for the parameter group. (2) Add object parameter. (3) Update callers. (4) Remove old params. (5) Run tests.

```typescript
// Before
function searchProducts(minPrice: number, maxPrice: number, category: string, inStock: boolean) {}

// After
interface ProductFilter { minPrice: number; maxPrice: number; category: string; inStock: boolean; }
function searchProducts(filter: ProductFilter) {}
```

### Replace Conditional with Polymorphism

**Recipe:** (1) Create base interface with the varying method. (2) Create subclass per case. (3) Move case logic into subclass. (4) Replace conditional with method call. (5) Run tests.

```typescript
// Before
function calculateArea(shape: Shape): number {
  switch (shape.type) {
    case "circle":    return Math.PI * shape.radius ** 2;
    case "rectangle": return shape.width * shape.height;
    case "triangle":  return (shape.base * shape.height) / 2;
  }
}

// After
interface Shape { area(): number; }
class Circle implements Shape {
  constructor(private radius: number) {}
  area() { return Math.PI * this.radius ** 2; }
}
class Rectangle implements Shape {
  constructor(private width: number, private height: number) {}
  area() { return this.width * this.height; }
}
class Triangle implements Shape {
  constructor(private base: number, private height: number) {}
  area() { return (this.base * this.height) / 2; }
}
```

### Decompose Conditional

**Recipe:** (1) Extract condition into a named method. (2) Extract then-branch if non-trivial. (3) Extract else-branch if non-trivial. (4) Run tests.

```typescript
// Before
if (date.getMonth() >= 5 && date.getMonth() `.

Dead code includes: unreachable branches, unused functions, commented-out blocks, unused variables and imports, removed feature flag code. Never comment out code "for later" -- version control preserves history.

## Strangler Fig Pattern

For large-scale refactors that cannot be completed in a single step:

1. **Identify the boundary** of the legacy code to replace
2. **Build the new implementation** alongside the old one
3. **Route traffic incrementally** using a facade or feature flag
4. **Verify each increment** in production
5. **Remove the old implementation** once all traffic uses the new code

```typescript
// Step 1: Facade delegates to old code
class PaymentProcessor {
  process(payment: Payment): Result { return this.legacyProcessor.process(payment); }
}

// Step 2-3: Route with feature flag
class PaymentProcessor {
  process(payment: Payment): Result {
    if (featureFlag.isEnabled("new-payment-processor"))
      return this.newProcessor.process(payment);
    return this.legacyProcessor.process(payment);
  }
}

// Step 4-5: After verification, remove old code
class PaymentProcessor {
  process(payment: Payment): Result { return this.newProcessor.process(payment); }
}
```

### Strangler Fig Checklist

- [ ] Both old and new paths are tested
- [ ] Rollback is possible at every stage by toggling the flag
- [ ] Monitoring and alerts cover both paths
- [ ] Old code is deleted only after the new path is proven in production

## Refactoring Workflow Summary

```
1. Identify the smell
2. Choose the named refactoring
3. Verify tests pass (write them if missing)
4. Apply one transformation
5. Run tests
6. Commit: "refactor:  -- "
7. Repeat from step 4 until the smell is resolved
```

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [Claude-Code-Community-Ireland](https://github.com/Claude-Code-Community-Ireland)
- **Source:** [Claude-Code-Community-Ireland/claude-code-resources](https://github.com/Claude-Code-Community-Ireland/claude-code-resources)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-claude-code-community-ireland-claude-code-resources-refactoring-patterns
- Seller: https://agentstack.voostack.com/s/claude-code-community-ireland
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
