What Is Refactoring?

The term “refactoring” has become quite popular in the workplace. We developers say, “I need to refactor this thing,” then proceed to rewrite a large chunk of code. From a big-picture view, this use of the term carries the same intent as its proper definition: we want to change the way the code does its work without changing its behavior. This matches the definition from the book Refactoring: Improving the Design of Existing Code, 2nd Edition [Fow18]:

Refactoring is the process of changing a software system in a way that does not alter the external behavior of the code yet improves its internal structure.

But the common use of the word ignores both the methodology and the mechanics shown in the book. We get no further than page 5 before the book explains:

Whenever I do refactoring, the first step is always the same. I need to ensure that I have a solid set of tests for that section of code. The tests are essential…

The reason tests are essential is that changing things around is risky. We can reduce the risk of breaking things by testing the changed code. The better the tests are, the safer the change becomes. The faster the tests are, the more often we can run them. And the more often we can run them, the smaller the steps we can take become.

Working in small, verified steps is a game changer. Many developers like to work with large changes. But if we practice refactoring as described in the book, the changes are very small. Let me summarize it this way: disciplined refactoring is changing code in small steps, with automated verification of each step.

Why do we want to change the internal structure of the code in the first place? Because this can make the code easier to read, understand, and modify. Often, adding new functionality will be faster and safer if we make other changes first. Kent Beck writes:

for each desired change, make the change easy (warning: this may be hard), then make the easy change[35]

In a fast-moving world, we strive to follow the Agile Manifesto[36] by valuing “responding to change.” (This is one of the four points of the manifesto.) But to accommodate these changes safely, our software must be malleable, not brittle. We need the freedom to restructure the internals of our code without breaking anything. This is why disciplined refactoring is important.

So unit testing has a tight connection with refactoring. Unit tests form the safety net that makes disciplined refactoring possible. Part III of this book focuses on the practical steps of what that kind of refactoring looks like.