Lesson 21.0

Orientation: what refactoring is, and the three goals you refactor toward

Artifact: A precise definition of refactoring and the three goals this chapter trains you on

1. The promise

You'll know what refactoring is, what it isn't, and the three goals this chapter trains you to refactor toward: readability, testability, and performance.

2. The mental model

Refactoring is like tidying a kitchen between dishes. The food on the counter stays the same. The knives go back in the block. The cutting board gets wiped. The next dish starts faster.

You don't change the menu while you tidy. You don't throw out the food. You leave the kitchen ready for the next cook.

Observable behaviour is what a caller, a user, or a test can see from the outside. If a test passes before your change and passes after, with the same assertions, you didn't change the behaviour.

(DIAGRAM: refactor vs bug fix vs feature — three-column comparison — annotated SVG — same total() function, three diffs, with "tests still pass with the same assertions" tick only on the refactor column)

3. You do it, with me

Open VSCode. Open any TypeScript project you've built before. The Ch 14 backend or the Ch 10 dashboard will do.

Pick one small function. Here are three changes you could make to it:

  • A bug fix. The function returns the wrong number on a leap year. You fix the date math. Behaviour changes.
  • A feature add. The function now takes a currency argument and formats the output. Behaviour changes.
  • A refactor. You rename a variable, split a long block into two smaller functions, and move one helper to its own file. Behaviour stays the same.

(SCREENSHOT: VSCode showing the same total() function in three side-by-side tabs labelled "bug fix", "feature add", "refactor" — the file diffs visible in the gutter — full window)

Only the third change is a refactor. The first two change what the function does. The third changes how the code reads.

Now the three goals you'll refactor toward in this chapter:

  • Readability. The next person can read it faster. You rename c to cart. You split a 60-line function into four 15-line ones. The behaviour is the same; the reading speed goes up.
  • Testability. The next person can test it without setting up the universe. You pull pricing logic out of a class that talks to the database. The pricing function now takes plain data and returns plain data. A test no longer needs a database.
  • Performance. The next person runs it without it being the slow one. You replace an Array.find inside a loop with a Map lookup. The output is the same; the runtime drops.

Most refactors aim at one of these three. Naming the goal up front keeps the scope honest.

(SCREENSHOT: Vitest terminal output showing all green tests after a refactor — full window — the "0 failed" line highlighted)

The chapter shape. You'll meet the smells first — the shapes of code that signal trouble. Then the named extractions: extract function, extract module, rename. Then the with-tests and without-tests workflows. Then the strangler-fig pattern for larger jobs. The tools come at the end.

You won't meet design patterns as a catalogue here. That belongs in Ch 27. You also won't meet rewrite-from-scratch as a refactor — it isn't one, and the chapter says when it's the right call anyway.

4. What you should be seeing

  • You can state the definition of refactoring in one sentence: a change to the structure of code that doesn't change its observable behaviour.
  • You can name the three goals: readability, testability, performance.
  • You can tell apart a refactor, a bug fix, and a feature add by looking at a diff.

If any of those three is shaky, re-read beats 2 and 3 before moving on.

5. Common stumbles

  • You call every code change a "refactor". The word means the specific kind of change that doesn't alter behaviour. Use it precisely or it stops being useful in code review.
  • You start a refactor and slip a small bug fix into the same commit. The reviewer can't tell which lines did which. Keep them in separate commits.
  • You want to refactor "everything" at once. Pick one goal. Refactor until that goal is met. Stop.

6. You should know

1/16
Next