Skip to content
Development
Skill

/refactoring-patterns

Improve code structure without changing behavior — the discipline of small, named, test-backed moves. Extract function/variable, inline, rename, replace conditional with polymorphism, introduce parameter object, guard clauses. Recognize smells, refactor safely, avoid big-bang

From plugin
vanara-agents-skills
917 skills54 agents
Install
$ npx -y skills add vanara-agents/skills --skill refactoring-patterns --agent claude-code

How it fires

How this skill gets triggered: by you, by Claude, or both.

  • Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
  • You can call itInvoke it directly when you want it.
  • Slash command/refactoring-patterns

Context preview

The summary Claude sees to decide when to auto-load this skill.

Improve code structure without changing behavior — the discipline of small, named, test-backed moves. Extract function/variable, inline, rename, replace conditional with polymorphism, introduce parameter object, guard clauses. Recognize smells, refactor safely, avoid big-bang

SKILL.md

refactoring-patterns.SKILL.md
name: refactoring-patterns
description: Improve code structure without changing behavior — the discipline of small, named, test-backed moves. Extract function/variable, inline, rename, replace conditional with polymorphism, introduce parameter object, guard clauses. Recognize smells, refactor safely, avoid big-bang rewrites.
type: skill
version: 2.0.0
updated: 2026-06-29

Refactoring Patterns

Refactoring is **changing the internal structure of code without changing its observable behavior**. It is not "cleanup whenever," and it is not rewriting. It is a disciplined sequence of small, *named*, behavior-preserving moves, each verified by tests, each committable on its own. Done right it is nearly risk-free; done wrong — without tests, mixed with feature work, or as a big-bang rewrite — it is one of the most reliable ways to ship a regression.

This skill is the deep reference for that discipline: the safety net that makes it possible, the named moves themselves, the smells that signal where to apply them, and the trade-offs of when *not* to. Heavy detail lives in `references/`; copy-paste before/after material in `examples/`; a runnable smell detector in `scripts/`.

The mental model

Two hats, never worn at once (Kent Beck's rule): you are either **adding behavior** (new tests go red, then green) *or* **refactoring** (all tests stay green the whole time). Switching hats mid-edit is the root cause of most refactoring disasters, because when a test breaks you can no longer tell whether your *restructuring* was wrong or your *new feature* was wrong.

| Question | Refactoring answer | |---|---| | What changes? | structure only — names, shape, location | | What stays identical? | observable behavior, the public contract, test results | | How do I stay safe? | tests green before, green after, green between every step | | How big is a step? | small enough that a broken test points at one change | | When do I commit? | after each move that leaves the suite green |

1. Tests are the safety net (non-negotiable)

You cannot refactor code you cannot verify. Before touching structure, ensure a **green** test suite exercises the behavior you're about to move. If coverage is missing, write **characterization tests** first — tests that pin down what the code *currently* does (even if that's arguably wrong), so any behavior drift during refactoring surfaces immediately. See `references/safe-workflow.md` for the red-green-refactor loop, characterization testing, and the strangler-fig pattern for large systems.

The loop:

1. Run the suite — confirm green. 2. Apply **one** named refactoring. 3. Run the suite — confirm still green. 4. Commit. 5. Repeat.

If step 3 goes red, you have exactly one small change to undo. That is the entire value proposition.

2. Smells: knowing *where* to refactor

Refactoring is demand-driven — you don't refactor everything, you refactor what a **code smell** is pointing at. The catalogue in `references/code-smells.md` is the full list; the high-frequency ones:

  • **Long method / long function** — does too much; the body has comment-delimited "paragraphs."
  • **Large class / god object** — too many fields and responsibilities; low cohesion.
  • **Feature envy** — a method that reaches into another object's data more than its own.
  • **Primitive obsession** — strings/ints standing in for real concepts (`string currency`, `int cents`).
  • **Shotgun surgery** — one conceptual change forces edits in many scattered places.
  • **Duplicated code** — the same logic in three spots (the rule of three: extract on the third copy).

3. The named moves

Each refactoring has a **name** and a **mechanics** (a precise step sequence). Naming them lets a team say "extract a function here" and share an exact, low-risk procedure. The full catalogue with mechanics is in `references/refactoring-catalog.md`. The core set:

  • **Extract Function** — pull a coherent block into its own named function.
  • **Inline Function/Variable** — the inverse, when the indirection earns nothing.
  • **Rename** — the highest-value, lowest-risk move; a precise name deletes a comment.
  • **Extract Variable** — name a sub-expression to explain it.
  • **Replace Conditional with Polymorphism** — swap a type-switch for dispatch on a type.
  • **Introduce Parameter Object** — bundle a clump of args that always travel together.
  • **Replace Magic Literal with Constant**, **Decompose Conditional**, **Replace Nested Conditional with

Guard Clauses**, **Move Function/Field**, **Separate Query from Modifier**.

Before / after: Extract Function + guard clauses

A long function doing validation, calculation, and formatting at once:

// before — one function, three jobs, deep nesting
function invoiceLine(item) {
  if (item) {
    if (item.qty > 0) {
      let total = item.qty * item.price;
      if (item.taxable) { total = total * 1.2; }
      return `${item.name}: $${total.toFixed(2)}`;
    }
  }
  return "invalid";
}
// after — guard clauses flatten nesting; intent-named helpers
function invoiceLine(item) {
  if (!isValid(item)) return "invalid";
  return format(item.name, totalFor(item));
}

const isValid   = (i) => i && i.qty > 0;
const totalFor  = (i) => i.taxable ? i.qty * i.price * 1.2 : i.qty * i.price;
const format    = (name, total) => `${name}: $${total.toFixed(2)}`;

Same inputs, same outputs — tests stay green — but each piece now has one job and a name.

Before / after: Replace Conditional with Polymorphism

// before — the switch will grow with every new type; shotgun surgery waiting to happen
function area(shape: Shape): number {
  switch (shape.kind) {
    case "circle": return Math.PI * shape.r ** 2;
    case "square": return shape.side ** 2;
    default: throw new Error("unknown shape");
  }
}
// after — each type owns its behavior; adding a shape is additive, not invasive
interface Shape { area(): number; }
class Circle implements Shape { constructor(private r:
Read more
Ships withvanara-agents-skills

🐒 Free agents, skills & packs for Claude Code One subscription. An army of Claude Code agents. 30 production-grade agents, skills, and packs for Claude Code — free, Apache-2.0, install with one command.

Get the whole plugin

Other skills on vanara-agents-skills.