---
name: aipatterns-refactoring
description: Apply 67 refactoring techniques - the 66 classics (Extract Method, Move Method, Replace Conditional with Polymorphism, Introduce Parameter Object) plus Consolidate Tools for agent-facing tool surfaces - as small steps. Each step preserves behavior, and tests stay green between steps. Use when a task asks you to refactor, clean up, simplify, restructure or "make this code better" without changing behavior. Use also when someone identified a code smell and needs its treatment.
license: MIT
metadata:
  source: https://aipatterns.dev/refactoring/techniques
  version: "1.0.0"
---

# Refactoring techniques

Refactoring changes structure, never behavior. If behavior must change too, do the refactoring first and the behavior change in a separate step.

## Rules

1. **Have a safety net.** Run the tests before you start. If there are none for the code you'll touch, write characterization tests first that pin current behavior, including the odd cases.
2. **Name the smell** you're removing. Use the `aipatterns-code-smells` skill if needed. No smell, no refactoring.
3. **Pick one technique**, open its reference, and read **Watch out** before **Steps**.
4. **Take the smallest step that compiles and passes tests.** Commit or checkpoint after each green step.
5. **Never mix** a refactoring with a feature change, a dependency upgrade, or formatting churn in the same step.
6. **Stop** when the smell is gone. Don't keep "improving" past the goal, and add no abstraction the confirmed smell does not require.
7. Summarize each technique applied, the smell it treated, and the test command you ran.

## Pick a technique by symptom

| Symptom                                                      | Technique                                                                                                                                                                                  |
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Long function, or a block that needs a comment to explain it | [Extract Method](references/extract-method.md), [Decompose Conditional](references/decompose-conditional.md)                                                                               |
| Function body is as clear as its name                        | [Inline Method](references/inline-method.md)                                                                                                                                               |
| Complex expression                                           | [Extract Variable](references/extract-variable.md)                                                                                                                                         |
| Temp reused for different things                             | [Split Temporary Variable](references/split-temporary-variable.md)                                                                                                                         |
| Method uses another class's data more than its own           | [Move Method](references/move-method.md), [Move Field](references/move-field.md)                                                                                                           |
| Class does two jobs                                          | [Extract Class](references/extract-class.md)                                                                                                                                               |
| Class does almost nothing                                    | [Inline Class](references/inline-class.md)                                                                                                                                                 |
| `a.getB().getC().doIt()`                                     | [Hide Delegate](references/hide-delegate.md)                                                                                                                                               |
| Class only forwards calls                                    | [Remove Middle Man](references/remove-middle-man.md)                                                                                                                                       |
| Primitive that carries rules (money, email, range)           | [Replace Data Value with Object](references/replace-data-value-with-object.md)                                                                                                             |
| Unnamed literal                                              | [Replace Magic Number with Symbolic Constant](references/replace-magic-number-with-symbolic-constant.md)                                                                                   |
| Getter returns a mutable internal collection                 | [Encapsulate Collection](references/encapsulate-collection.md)                                                                                                                             |
| Type code drives `switch` statements                         | [Replace Type Code with State/Strategy](references/replace-type-code-with-state-strategy.md), [Replace Conditional with Polymorphism](references/replace-conditional-with-polymorphism.md) |
| Agents chain several thin API tools for one task             | [Consolidate Tools](references/consolidate-tools.md)                                                                                                  |
| Deep nesting from edge cases                                 | [Replace Nested Conditional with Guard Clauses](references/replace-nested-conditional-with-guard-clauses.md)                                                                               |
| Repeated `if (x == null)`                                    | [Introduce Null Object](references/introduce-null-object.md)                                                                                                                               |
| Same parameters travel together                              | [Introduce Parameter Object](references/introduce-parameter-object.md), [Preserve Whole Object](references/preserve-whole-object.md)                                                       |
| Function both returns a value and mutates state              | [Separate Query from Modifier](references/separate-query-from-modifier.md)                                                                                                                 |
| Boolean flag parameter switches behavior                     | [Replace Parameter with Explicit Methods](references/replace-parameter-with-explicit-methods.md)                                                                                           |
| Error codes returned instead of raised                       | [Replace Error Code with Exception](references/replace-error-code-with-exception.md)                                                                                                       |
| Duplicate code in sibling classes                            | [Pull Up Method](references/pull-up-method.md), [Form Template Method](references/form-template-method.md)                                                                                 |
| Subclass refuses most of what it inherits                    | [Replace Inheritance with Delegation](references/replace-inheritance-with-delegation.md)                                                                                                   |

The six category files list every technique: [composing methods](references/composing-methods.md), [moving features between objects](references/moving-features-between-objects.md), [organizing data](references/organizing-data.md), [simplifying conditional expressions](references/simplifying-conditional-expressions.md), [simplifying method calls](references/simplifying-method-calls.md), and [dealing with generalization](references/dealing-with-generalization.md).

## Inverse pairs: don't oscillate

- Extract Method ↔ Inline Method
- Extract Class ↔ Inline Class
- Hide Delegate ↔ Remove Middle Man
- Pull Up Method ↔ Push Down Method
- Replace Inheritance with Delegation ↔ Replace Delegation with Inheritance
- Change Value to Reference ↔ Change Reference to Value

If you plan to apply the inverse of a step you just made, stop and re-check the goal.

## Agent checklist

- [ ] The tests passed before the first change and pass after the last.
- [ ] Each step was a single named technique.
- [ ] No public API changed unless the task asked for it. If it did, you updated every caller.
- [ ] The smell you named is gone, and you added no new smell.
