Skip to content
aipatterns.dev

Guide

When to Refactor

Refactor right before you change code, while fixing a bug and during review. Skip it when the code is due for deletion or has no tests.

Also known as
Refactoring triggers

The short answer

Refactor the code you are about to change, right before you change it. That is when the cost of bad structure is real and the benefit lands immediately. Refactoring code that nobody will touch again is spending money on a building scheduled for demolition.

Good moments

Before adding a feature

Read the area you need to change. If the feature would be awkward to add, first reshape the code so the feature becomes a small, obvious addition. Make the change cheap first, then make the cheap change.

Typical sequence:

  1. The new payment method needs a fourth branch in a Switch Statements block that already has three.
  2. Apply Replace Conditional with Polymorphism or extract a Strategy map. Tests stay green.
  3. Add the new method as one new class or function.

When fixing a bug

A bug is evidence that the code is hard to understand. Before fixing it, restructure enough to make the bug visible: Extract Method to name the steps, Decompose Conditional to name the conditions. Often the bug becomes obvious. Then write a failing test, fix, and commit the refactoring and the fix separately.

The rule of three

The first time, write it. The second time you write something similar, note the duplication. The third time, extract the shared part. Two copies may diverge for good reasons; three copies are a pattern. See Duplicate Code.

During code review

Review is where a second reader finds names that mislead and functions that do too much. Small renames (Rename Method) and extractions are cheap to apply while the author still has context.

When you need to understand code

Renaming a variable once you understand what it holds stores that understanding in the code. The next reader, human or agent, does not need to rediscover it.

Bad moments

  • The code works, is not changing and has no pending work. Leave it. Ugly but stable code has zero interest.
  • The code is scheduled for deletion or replacement. Spend the effort on the replacement.
  • There are no tests and you cannot add them cheaply. Refactoring without verification is guessing. Add characterization tests first, or restrict yourself to IDE-automated, provably safe transformations (rename, extract with a tool).
  • You are close to a deadline and the change is not on the critical path. Record the debt (see Technical debt) and come back.
  • The rewrite is honestly cheaper. If the code is so broken that it does not work, refactoring has nothing to preserve. Restructuring assumes correct behavior worth keeping.
  • The task is not yours. An agent asked to fix one bug should not restructure three unrelated modules. Scope creep makes diffs unreviewable.

Decide in one pass

QuestionIf yesIf no
Will you change this code in the current task?ContinueDo not refactor
Do tests cover the behavior you will touch?ContinueAdd tests first, or stop
Would the task's diff be clearly smaller or safer after restructuring?Refactor firstMake the change directly
Does the refactoring stay inside the files the task already touches?ProceedNote it, do not do it now

Signals in the code

The smell catalog lists symptoms worth acting on. The most common triggers:

  • A function longer than a screen: Long Method.
  • A change that needs edits in many files: Shotgun Surgery.
  • A method that uses another object's data more than its own: Feature Envy.
  • The same group of three or four parameters passed everywhere: Data Clumps.
  • Comments explaining what a block does: Comments.

Agent checklist

  • The code you plan to refactor is in the path of the current task.
  • Tests cover the behavior, or you added characterization tests first.
  • You can state the concrete way the refactoring makes the task smaller or safer.
  • The refactoring stays within the scope the user asked for; anything broader is reported, not done.
  • Refactoring and behavior change land as separate commits or separate steps.

See also

Original writing and examples. Topic coverage follows Refactoring.Guru, which explains this topic with its own illustrations.