Don’t mix refactorings with behavior changes

by Jason Swett,

Why it’s bad to mix refactorings with behavior changes

It adds risk

Probably the biggest reason not to mix refactorings with behavior changes is that it makes it too easy to make a mistake.

When you look at the diff between the before and after versions of a piece of code, it’s not always obvious what the implications of that change are going to be. The less obvious the implications are, the more opportunity there is for a bug to slip through.

When you mix behavior changes with refactorings, the behavior change and the refactoring obscure each other, often making the change substantially harder to understand and allowing for a much greater opportunity for bugs to slip through.

Mixing refactorings with behavior changes also requires you to make your deployment deltas (i.e. the amount of change being deployed) bigger. The bigger the delta, the greater the risk.

It makes bug attribution harder

If I deploy a behavior change that was mixed with a refactoring, and then I discover that the deployment introduced a bug, I won’t know whether it was my refactoring or my behavior change that was responsible because the two were mixed together.

And then potentially I’m forced to do something painful in order to remove the bug, which is to roll back both my behavior change and my refactoring, even though only one of those two things was the culprit and the other one was innocent. If I had committed and deployed these changes separately, there’s a higher chance that I would be able to attribute the bug to either the refactoring or the behavior change and not have to roll back both.

It makes code review harder

When you mix refactoring with behavior changes, it’s hard or impossible for a reviewer to tell which is which. It makes a discussion about a code change harder because now the conversation is about two things, not just one thing. This makes for a potentially slow and painful PR review process.

How to approach refactorings instead

When I’m working on a behavior change and I discover that my work would also benefit from some refactoring, here’s what I do:

  1. Set aside my current feature branch
  2. Create a new branch off of master on which to perform my refactoring
  3. Merge my refactoring branch to master (and preferably deploy master to production as well)
  4. Merge or rebase master into my feature branch
  5. Resume work on my feature branch

This allows me to work in a way that reduces risk, allows for easier bug attribution, makes code review easier, and generally saves a lot of time and headache.

Leave a Reply

Your email address will not be published.