The benefits and pitfalls of code refactoring

Code refactoring is a very important weapon in programmers’ arsenal allowing them to combat technological debt. But as beneficial as it is, it is equally hated by project owners who get convinced into refactoring by the developers, although the tangible effects of the process may only be felt by the development department.

If the developer considers the code “bad” or finds its further development inefficient or simply impossible, he will very likely suggest refactoring it.

  • What is "bad" code?
  • When do you really need refactoring?
  • How to justify the need for refactoring?
  • Does refactoring bring any risks to the project or business?
  • How to tell if the refactored code is good enough?

I will try to answer these questions in this article.


Code refactoring - Definition

According to Martin Fowler:

"Code refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior."

Looking at the above definition through the eyes of the client, you could ask: "If there is no difference, why do it in the first place?"

Experienced developers, project managers, clients and aware software development companies know that refactoring is an integral part of the software development process and without it it is hard to imagine the long-term development of any application.

Concept development on whiteboard
Refactoring is an internal part of the development process

However, in each project there are situations where we create new functionalities without putting much thought into the process – simply because the deadline is chasing us. The newly added functionalities entail changes in other parts of the code, but there is no time for proper refactoring, so we end up with code that “just works”. We introduce a number of additional changes over time until the project reaches a tipping point where the code becomes too complicated, bloated, incomprehensible, difficult to test, or even unpredictable. This makes the implementation of new functionalities slower, and in extreme cases even impossible.


When is the right time for refractoring?

My experience as a developer shows that from the project owner’s point of view there is never a good time to do refactoring. The effect of refactoring will most likely be visible only in the long term (the exception may be refactoring associated with optimization). I believe the best way to keep code refactoring a part of everyday work is to make everyone (including product owners and project managers) aware of what it really is. They need to know that this is a necessary part of the developer's work, and not just the consequence of poorly written code. Refactoring is an integral element of software development and should not be treated as an additional task that's completely detached from everyday work. Perhaps not every developer is fully aware of this, but during the daily implementation of tasks in the sprint some form of code refactoring is performed every now and then. It may be an innocuous change of a variable's name, but it also counts as refactoring, and should be an integral part of the programming process.

However, it is important not to lose yourself in the heat of constant change and code improvement. Refactoring should not be an end in itself. The ultimate goal of the project is to bring tangible benefits (usually financial ones) that will cause the project to develop and meet the client’s expectations. Unilateral satisfaction in the form of a satisfied programmer is unfortunately not enough and this approach can lead to the collapse of the project.


Is my code perfect?

"This code is not good enough, you have to write it again" – this is probably the most common phrase programmers use in conversations about refactoring a piece of code.

At other times, the developer performing refactoring loses himself in the code, beautifying it until he vastly exceeds the time allocated for the implementation of the task. Time flies and the system is not gaining any new functionalities, and the bugs are still there.

And, finally: time flies, and the project owner and the developer themselves are still not satisfied with the results. Having fallen into this vicious circle, the developer constantly sees new opportunities for improvement, and the project owner is stuck in a situation where the task drags on and on with no end in sight.

In that case, when can we assume that the code is perfect and does not require more attention? The answer is:

"There is no such thing like perfect code. Code can only be good enough."

When doing refactoring, you have to be able to say to yourself – "Ok, this is good enough, and the result satisfies me at this point. We can consider this quality as acceptable." You can't polish one piece of code indefinitely while neglecting everything around it. But it doesn't mean you have to accept anything.

If you work in a project where work is not only about refactoring, but primarily involves continuous development of new functionalities and delivering them to the client within the set deadlines, your focus should be on progress and not on continuous pursuit of excellence.

“Done is better than perfect”

Accept the fact that you'll never be 100% happy. The code you are currently refactoring will also become obsolete and require refactoring again in the near future. The best technical solution is not always the best for the project and constant refactoring is very often mere cosmetics that won't affect the functionality of the application.

Teammates help
Help from another developer may be crucial in code refactoring


How to minimize threats? - Best Practices

  • At the beginning of the refactoring process, before making the first change, it is worth setting clear boundaries – what and how we change, and what we don't change. This will help avoid uncontrolled extension of the scope during work.
  • If you came across a piece of code that needs refactoring but is not a matter of life or death – and you are left with little time on your hands to meet the deadlines – do not do it. If your desire for refactoring stems mainly from your love of beautiful, clean code, and doing so goes against the deadlines and assumptions of the company and the project, you are probably a narcissistic programmer. Your striving for perfection may not always be the best strategy for business.
  • When implementing refactoring, ask other developers for a preliminary design review. Such an inspection of the idea doe early enough will allow you to verify the flow and the proposed architecture before it is implemented, and perhaps save you a lot of time.
  • Don't refactor if you see that you don't have enough time and the deadline is round the corner. This stage in the project would benefit more from debugging than refactoring.
  • Write tests for your code. In the case of refactoring, tests will allow you to easily and quickly control the dependencies and changes that occurred in the refactoring process.
  • In a situation when the development team takes over the project after another team, you should make sure you don’t make hasty decisions about refactoring the application (in such situations, the first words you hear are the usual – "let's rewrite it"). Developers will always complain that other people's code is written poorly and needs improvements. In fact, it is more important to read the code and learn its strengths and weaknesses in the beginning. Many programmers think code is bad just because it is incomprehensible to them – this is not true. When starting the project, the first weeks should focus on developing functionalities or eliminating potential bugs. Any decisions regarding refactoring should be made consciously and only after getting to know the application.
  • Try not to refactor a large piece of code, as this raises the risk of blocking the development of code elements associated with other developers' tasks. This approach requires good planning for the entire development team.
  • It is not worth doing refactoring just because a developer stumbled upon a technological novelty he wants to play with. First, take some time to see how it will be received by the development community and whether there will be any critical errors or problems arising from its implementation. It may turn out that the innovation is not as cool as it initially seemed and may create a new problem you’ll have to handle.
  • Good communication with the Project Manager / Project Owner and the rest of the team is important whenever refactoring gets out of hand. Let's not be afraid to speak loudly about the progress of the work. Others may notice than us that we are heading in the wrong direction.


Summary

Code refactoring is an important and necessary tool but it should be used with caution. Its improper use may have a negative impact on project development and deadlines. It is worth using only known and proven refactoring techniques to achieve the desired result. The energy that we devote to the delusive and disastrous pursuit of perfection of our code can be better spent on the actual development, which will allow us to increase awareness of the available tools, business operations, customer understanding, and the overall functioning of the company.