Newcomers to the concept of refactoring in agile are often confused by it. Isn't it dangerous to change code that works? What's the value in it? If you do it right, refactoring is not only safe but also beneficial.
This post will give you a comprehensive introduction to refactoring in agile. You'll learn more about what it is, what its benefits are, and how and when you should do it.
What Is Refactoring?
Let's start by briefly covering some fundamentals of refactoring.
Martin Fowler literally wrote the book on refactoring—called, appropriately enough, Refactoring. Here's how he defines the practice:
"Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."
In other words, it is changing the code in a way that doesn't change what it does. Additionally, refactoring can be a noun that refers to every small transformation you can do to your code.
Why Refactor Code?
Why on Earth would you want to change code that already works? In short, you refactor code to improve it: to make it easier to understand and change.
When refactoring, you can:
- remove code duplication,
- make code less complex (e.g., by splitting a large class into smaller ones), and
- pay off technical debt before starting a new feature.
Agile preaches continuous and incremental delivery of working software, so refactoring fits it perfectly.
In fact, it is a core tenet of extreme programming (XP). On the other hand, scrum doesn't mandate that you refactor since it's not prescriptive about engineering practices. But you can, of course, apply refactoring if your team uses scrum.
How to Refactor Code?
With the "what" and "why" out of the way, the next big question is "how."
Learn the Existing Patterns
It's important to remember that refactoring doesn't mean simply changing code at random. Quite the contrary: there are refactoring patterns, each with a name and a clear set of instructions. They're almost like small "recipes" you can use to make your code better!
Some of the most popular refactoring patterns include
- extract method,
- extract class,
- inline method,
- rename variable,
- consolidate conditional expression,
- remove dead code, and
- replace conditional with polymorphism.
The first step to refactoring is learning about those "recipes." For that, you can read the book mentioned above by Martin Fowler or consult the online catalog.
Have a Comprehensive Suite of Tests
Every time you make a change to a codebase, there's a risk you'll break something. Such is the nature of software. Such risk exists when you're fixing a bug, introducing a new feature, and, yes, when you're refactoring.
So, to refactor safely, you must have a safety net to protect you in case anything goes wrong. And the most trustworthy safety net you can have is a suite of automated tests, composed mostly of fast and reliable unit tests.
With a comprehensive suite in place, you'll be notified if you break something, making the refactoring process way safer.
Additionally, tools like LinearB can detect branches that contain a high level of code changes and a high level of rework or refactor. You should check out the high-risk work during the iteration in order to see which branches need your attention as a manager, more review, and more testing.
Rely on Your IDE
As a software engineer, you should always strive to use automation to make your life easier. There's no reason this shouldn't apply to the refactoring process as well.
Nowadays, most modern IDEs can perform many of the most common refactoring patterns, such as extracting methods; renaming variables, functions, and classes (and automatically updating all references to said names); extracting classes; and so on.
The productivity boost you can obtain by using such features is considerable, so there's no reason not to use them if they're at your disposal.
When Is the Ideal Time for Refactoring?
The last big question we have left regarding refactoring in agile is "when." More specifically, people disagree on whether you should refactor during specific times or do it constantly. What's correct?
I can understand why some people might prefer to refactor in batch—for instance, to allow finishing features earlier. But in my experience, reserving time for certain activities—be they refactoring, testing, or documentation writing—simply doesn't work. More pressing issues will appear, and the other activity will be abandoned.
If it's important, do it constantly. In his new book Code That Fits In Your Head, Mark Seemann says:
"In software development, later is never."
I couldn't agree more. Refactor constantly.
The Role of Refactoring in TDD
I've already covered the close relationship between refactoring and unit tests—tests are essential for safe refactoring. Another way they're are related is through test-driven development (TDD).
TDD is a software development methodology in which automated unit tests are used to drive the development of new features. It happens in an iterative cycle composed of three phases, usually called the red-green-refactor cycle:
- You start by writing a test for the feature you'll implement. The test will fail since the feature doesn't exist yet.
- Then, you write the simplest amount of code necessary for the test to pass.
- Finally, if needed, you refactor the code to remove duplication and fix other problems.
If you don't have any experience working with TDD, I recommend you at least give it a try. By following the TDD cycle, you're guaranteed to perform refactoring at least a few times a day.
Is Refactoring a User Story?
Finally, one last question. Should refactoring sessions get their own separate task? I'll assume you use scrum. Should you create refactoring stories, have the developers assign them points, and implement them during the sprint?
My opinion on this should be clear at this point. No, you shouldn't. Refactoring doesn't get to be a separate programming task. Much like unit testing, refactoring in agile is an essential activity in the software development process.
Here's what Martin Fowler says:
"Refactoring isn't a special task that would show up in a project plan. Done well, it's a regular part of programming activity."
Refactor Your Code; Improve Its Health!
Refactoring in agile is arguably more important than refactoring in other software development methodologies. After all, agile is all about constantly delivering software that works at a sustainable pace. Refactoring is a powerful enabler of constant delivery of working software.
In this post, we've discussed the definition of refactoring. You've learned more about how it's done and why it's valuable. I've also shared my views on when you should do it (all of the time).
Before I go, I'll share another reason to prefer constant refactoring—especially if done in the context of TDD. It prevents excessive churn (or rework) after a file is initially created. How? If your process has refactoring built in, you'll keep code quality high, avoiding the issues that cause unnecessary rework.
Is there something more agile than avoiding waste and focusing on what delivers the most value? I don't think so.