Refactoring is changing the structure of code without changing what it does. The moment behaviour changes too, it isn't refactoring — it's a rewrite with no way to tell whether you broke something.

The rules

One kind of change at a time. Rename things, or extract a function, or reorder — not all three. Mixed changes produce diffs nobody can review, including you.

Never refactor and add a feature in the same commit. When something breaks afterwards you need to know which half caused it.

Commit before you start. Non-negotiable.

Have a way to check. Tests are ideal. Failing that, a written list of things to click through. Refactoring with no verification is just editing and hoping.

Order of safety

Roughly, safest first:

  1. Renaming. Almost risk-free with a good editor, and often the biggest readability gain available.
  2. Extracting a function from a block of code. Mechanical, and easy to check.
  3. Removing dead code. Safe if it's genuinely dead — verify rather than assume.
  4. Reordering so related things sit together.
  5. Changing an interface — parameters, return shapes. Now you're touching callers.
  6. Restructuring across files. The riskiest, and the one to do last if at all.

Ask for it narrowly

refactor-safely.txt
Refactor this for readability only. Behaviour must be identical —
same inputs, same outputs, same side effects: <paste>

- Do ONE kind of change: <renaming / extracting functions / whatever>.
- Tell me first, in two lines, what makes this hard to read.
- Then the change.
- Then everything I should test to confirm nothing changed.

Don't fix bugs you notice — tell me about them separately and leave
them in place. I want this diff to be behaviour-neutral.

That last instruction matters. A refactor that also fixes a bug is a refactor you can't verify by checking that nothing changed.

Know when not to

Code that works, that you rarely touch, and that nobody has to read is fine as it is. Refactoring has a cost and no user-visible benefit — spend it where you're actually working.

If you can't say what specifically is hard about the current code, don't refactor it. "It feels messy" produces changes that are different rather than better.