Why "targeted change" beats "confident rewrite," almost always
Handed a messy function inside code you don't fully understand yet, the tempting move is to rewrite it cleanly from scratch — you can see what it should look like, so why not just write that? This is the single most commonly flagged mistake in refactoring rounds, for a concrete reason: a rewrite makes it much harder for a reviewer (or for you, five minutes later) to verify that behavior was actually preserved, because there's no small, checkable step-by-step correspondence between old and new — just two versions and an assertion that they're equivalent. A targeted, incremental change, by contrast, is verifiable at every step: you can point at exactly what changed and why, and rerun the tests after each individual step to confirm nothing moved.
The precondition: tests first, always
Refactoring is only "safe" relative to a safety net that can tell you if you broke something — which means the Characterization Tests subtopic's technique is a hard prerequisite here, not optional prep. If the code you're asked to refactor has no tests, writing a handful of characterization tests first — even quick, unglamorous ones — is not a detour from the refactoring task, it is the first step of the refactoring task. Skipping straight to restructuring untested code because "it looks simple enough to get right" is exactly the failure mode this round is designed to catch.
Decompose the refactor into steps you could stop between
The core discipline: break a refactor into a sequence of small transformations — extract a function, rename a variable, inline a temporary, pull a conditional into its own guard clause — where each individual step is, on its own, a complete and correct improvement, verifiable by rerunning the test suite before moving to the next one. This has two concrete benefits under interview time pressure specifically:
- You always have a fallback. If you run out of time after step 2 of a planned 4-step refactor, you're not left with a half-broken rewrite — you're left with code that's strictly better than where you started and still fully passes its tests. Partial credit is real credit here.
- Each step is independently reviewable. An interviewer watching you extract one function, rerun tests, see green, and only then move to the next change can follow your reasoning in real time — compare that to watching someone restructure four things simultaneously and then run the tests once at the end, hoping.
Preferring your tools' automated refactors when they exist
Most modern IDEs implement common refactors (extract method/function, rename symbol, inline variable, move to a new file) as automated, behavior-preserving transformations — using them, out loud, is a legitimate and often stronger answer than doing the equivalent by hand. Saying "I'll use the IDE's rename-symbol refactor here so I don't have to hunt down every usage manually" demonstrates both efficiency and an understanding of why the automated version is safer (it can't miss a usage the way a manual find-and-replace can) — it's not a shortcut that reads as low-effort, it reads as knowing your tools.
Naming the refactor you're doing, not just doing it
A small habit that reads well and costs nothing: name the specific refactor as you do it — "I'm going to extract this into its own function," "I'm inlining this variable since it's only used once and the extra name isn't adding clarity" — rather than silently restructuring and letting the interviewer infer your reasoning after the fact. This mirrors the narration habit from Working Under Observation, applied specifically to the moment-by-moment structure of a refactor.
A concrete way to practice the decomposition itself
The Tennis Refactoring Kata is deliberately small and deliberately messy — a full scoring function that's easy to understand functionally but awkward structurally. The useful constraint to practice under: don't let yourself make more than one kind of change (one extraction, one rename, one guard clause) before rerunning the tests and confirming green, even when a bigger simultaneous change feels faster.