Steven's Knowledge

Refactoring

A discipline for improving the structure of existing code without changing its behavior

Refactoring

Refactoring is the practice of improving the internal structure of code while preserving its observable behavior. The discipline is older than the term — engineers have always cleaned up code — but Martin Fowler's catalog gave the practice a vocabulary and a method.

Three properties separate refactoring from "rewriting" or "tweaking":

  1. Behavior is preserved. External behavior, including known quirks, is the same before and after.
  2. Steps are small. Each step is small enough that, if interrupted, the system is still working.
  3. Tests are the safety net. Without trustworthy tests, what looks like refactoring is gambling.

The Two Hats

Kent Beck's framing: at any moment you are wearing one of two hats.

  • Adding-feature hat. New behavior is being added. Structure is left alone except as needed for the feature.
  • Refactoring hat. Structure is being improved. No new behavior is added; no tests change semantically.

You can switch hats often, but you cannot wear both at once. Mixing the two produces changes that are hard to review, hard to revert, and hard to reason about.

Why Refactor

The arguments for refactoring are economic, not aesthetic:

  • Lower the cost of the next change. Code is read far more than it is written; the cost of clarity is paid once and recovered repeatedly.
  • Reveal design. Structural improvements often expose missing abstractions or misplaced responsibilities that the original design did not see.
  • Find defects. Reading code carefully enough to refactor it surfaces bugs that scanning never would.
  • Sustain pace. Without periodic refactoring, every change becomes more expensive than the last; with it, the team retains the option to move quickly.

Refactoring without these payoffs is a hobby, not engineering. The discipline is to refactor when it pays — and resist when it does not.

Section Contents

  • Code Smells — A diagnostic vocabulary for spotting code that probably needs work.
  • Techniques — A working set of mechanical refactorings, when to use each, and what they buy you.
  • When to Refactor — Choosing the right moment, and recognizing the wrong one.

Prerequisites

Refactoring without these is not refactoring; it is risk:

  • Tests that exercise the behavior being preserved. Unit tests at the level being changed; integration tests for cross-module work.
  • Version control with cheap branching and revert. Every refactoring step should be a candidate commit.
  • Continuous integration. Mistakes should surface within minutes, not days.

When these are absent, the first work is to put them in place — by adding characterization tests that capture the existing behavior — before any structural change.

On this page