In any project, there quickly arises a need for what we call refactoring. This is especially true in legacy projects. But what do we mean by refactoring exactly, and why is it so important?
Refactoring: New Wine in Old Bottles?
Wikipedia defines refactoring as follows:
Code refactoring is the process of restructuring existing computer code—changing the factoring—without changing its external behavior. Refactoring improves nonfunctional attributes of the software.https://en.wikipedia.org/wiki/Code_refactoring
So what this means is that developers change the underlying structure of the code, i.e. change the implementation, of existing features and functionality. But those existing features and functionalities keep working the way they used to.
Take an online accounting application for example. Refactoring could mean anything from changing the underlying database to just changing the code that calculates a single value. As long as nothing visibly changes for the user, we can call this pure refactoring.
Often, refactoring can go hand in hand with new features. It’s not uncommon to have to refactor pieces of code in order to more easily add a new feature.
Why Bother With Refactoring?
So if refactoring means changing the code, with no changes for the user, why should we bother? We’re not adding any business value! Is this just throwing money out the window?
Definitely not. There is several cases where refactoring is necessary.
Paying Off Technical Debt
Refactoring is often paying off your technical debt. Many applications have pieces of code that work, but are confusing or need performance improvements, for example.
These pieces of code are hurting your business. If you only have a few such pieces, then you’re probably fine. But as your application grows and evolves over time, there are more and more such pieces, and development of new features starts to suffer. You have taken on too much technical debt, and should start paying back.
Refactoring is important in this situation because it allows your developers to write better code faster again and reduces the risk of introducing bugs.
You can compare it with the wiring behind your television. As you add more gaming consoles, set-top boxes and other devices, the wires become a tangled mess. At a certain point, adding new devices becomes a difficult job. But after you take some time to untangle everything, it’s easier to see how everything is connected and how you can add new stuff again.
Allowing New Features
Sometimes, new features can’t be implemented before some refactoring has been done. This can be caused by the previously mentioned technical debt issue. But it can also be because new features require a technical implementation that doesn’t fit into the current code.
A final case where refactoring is necessary, is when technical requirements change. Examples are:
- API’s you depend become deprecated
- You need to change an underlying technology (like the database)
- Security issues
- Standards that are being enforced
Whatever your reason, sometimes you need to refactor code for pure technical reasons, with little benefit to users or even developers.
Refactoring: Risking Bugs?
Is refactoring dangerous? Won’t we have an increased risk of introducing bugs that previously weren’t there?
Yes, that is undeniably so. But the risk is often worth it, and there are ways to reduce this risk.
The risk is worth it because leaving code unrefactored for too long leads to a major legacy project that becomes increasingly hard to fix. It leads to more and more bugs after every release, putting you in a worse situation than you were if you had refactored on time. It also reduces developer productivity over time. Refactoring now is a way of keeping quality and productivity high.
Even if you’re prepared to take the risk (which you should be), it’s still worth reducing said risk.
First, you can try to minimize the amount of code that you will be refactoring. There’s no need to refactor everything at once. It’s safer (and easier) to take little steps and work towards a goal. This approach also allows room for still creating business value in the form of new features.
Second, before you start refactoring, you should have automated tests for the code that will be refactored. It doesn’t really matter what type of test, as long as you can verify the behavior of code before you start changing it. Then you can run the tests again after the refactoring, and all tests should still pass. This will give you more confidence that you aren’t introducing any bugs.
Refactoring: Worth the Effort
Refactoring is the practice of changing code without changing its external behavior. This might not seem valuable, but not refactoring problem areas in your code leads to bugs and low productivity over time. Just be sure to do it gradually and have automated tests ready.