If we talk about program development and maintenance, we must talk about “Refactoring” too. If the word “Refactoring” does not resonate with you, chances are that either:
– you are a fresher, or
– you are not aware of it, or
– you don’t like it, or
– you find it hard to do it
Most of the seasoned engineers I have worked or interacted with just love to talk about refactoring. Still, we don’t often come across many blogs, articles, tutorials, videos or courses that talk about it, explain it, or exemplify it. No wonder there is a lack of understanding and informative discussions on the concept. In this blog post, I am not going to describe what refactoring is (the “What” part) or what are the different ways of refactoring (the “How” part). I will cover them in some other article. What I’m going to tell you in this article is the “Why” part. I know most of you do your knowledge work with intentions and you would not want to learn something only for the sake of knowing it. Through this article, I am going to discuss why you should start learning “Refactoring” and why you should implement that learning in your work from time to time in a structured way.
In the famous book “Refactoring”, written by Martin Fowler, two definitions of refactoring are given:
“A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.”
The other one:
“To restructure software by applying a series of refactoring without changing its observable behavior.”
You can get a fair understanding of what refactoring is from the above two definitions. In addition to these, I would also go a step up and say that Refactoring is an intentional and genuine willingness of a software engineer to improve the quality and design of software, to make it better.
Why am I saying so?
You see, you can go through all the refactoring techniques, learn them and note them down. But time-to-time if you are not implementing them in your work to make your product better, you are not utilising its true potential. Often in the community, we hear these sentences a lot –
“If something is working fine, don’t touch it” or
“Just get it done”
I have faced criticism multiple times when I changed the internal structure of some code even though there were no issues/changes with the external behavior of the program.
“Sumon, why have you changed this code if it is not related to the defect you are fixing?”
“I don’t think it was a good idea to change something which was already working fine, Sumon. Can you revert those changes and raise a fresh PR?”
I think many who try to do refactoring, get this pushback. Mainly from people who advocate that you should not touch something if it is working fine. But they are missing the bigger picture here.
We can’t be agile without refactoring
How do we start writing code for a product? We get some design or write some design ourselves, that is based on the requirements known at that time and start coding based on those requirements. In this age of agile, from time to time, requirements keep on changing or new requirements are added to the existing ones. The only constant is “change” and we have to embrace the change. But considering those changes, do we often make required modifications to the program design we are writing? Most often people don’t. What they do is – keep on adding features or make those required changes and try to accommodate them in the existing design – in all possible ways. Gradually, the initial design, based on which the code was written, starts to decay. If this goes on and on, there comes a time when the code becomes so complex that adding new features or fixing a complex bug becomes a nightmare for the engineers working on it. In software development or maintenance, there is always a scope for design improvement. No one can say that the design is perfect at a certain point of time in the development work. No one can write perfect code in a single sitting or after multiple sittings. It is an iterative, never-ending refactoring of the code that keeps it relevant and agile enough to cater to requirements gracefully.
We can’t improve code quality without refactoring
In the year 2020, I wrote an article for a platform titled “7 Proven Methods to Increase Your Automation Code Quality”. In that article, I described in detail what are the different things that will help us to increase the quality of our code and how can we implement them. I will be naive if I say that the first code that we write is of the best quality and we cannot further improve the code quality. Often when I write a code and after a few days when I see the same code, I say to myself-
“No way I have written this. It could have been much better”
As engineers, every day we are learning something and improving ourselves. We read a lot of code from our peers or blogs/articles/tutorials. Our understanding of code quality gets fine-tuned with experience. It always makes sense to take that understanding and improve the quality of the code that we are working on. But how can we do that if we are not refactoring it? Not in an ad-hoc way, but in an efficient and controlled manner by using the refactoring techniques. Note that ad-hoc refactoring is quite risky, systematic refactoring is what we should be doing.
Refactoring enables us to write code faster
At first thought, it might make sense to not refactor any part of the code when you have other work to do, timelines to meet, bugs to fix etc. We all work with timelines, most of the time. You, or your leadership, may think why spend time changing some internal structure of the code when the project wants to move faster? It is somewhat true. After all, you are taking your valuable time out of your busy schedule and making those changes. But it is not as straightforward as it looks. If we compromise design improvement and code quality to move faster today, we are not looking at the bigger picture for tomorrow. We are only looking at short-term goals. In the long run, all these compromises will make the project move much slower. You may need a design change to put up with the requirements. You may find it difficult to understand the code to fix critical or complex bugs. Your team or a new joiner in the team may find it hard and time-consuming to understand what the functions do. In some cases, all these hurdles have the potential to completely stop the project.
Refactoring helps us to learn and find important bugs
Two very important characteristics of refactoring are:
- we don’t make any changes to the existing behavior of the code while restructuring or adding code internally.
- we always refactor with “tests” being our refactoring guide
Refactoring is the only driver which makes us go through each line of the existing program, understand them and enable us to make continuous small changes to improve its design. The process is guided by well-written tests so that we quickly become aware if any change is breaking the existing behavior. While going through the code we learn a lot about
- what the code is doing.
- what can be added or deleted to improve it?
- do we need to add any tests?
- do we need to delete any tests?
- can the performance be optimised?
- can a design pattern be replaced with another design pattern?
All this knowledge helps us not only understand the product better but also increase our overall knowledge base of software development. They also help us to find subtle intermittent, deep, hidden bugs that the customers haven’t come across yet.
From the above points, I hope it has become clear now why you need to refactor your code from time to time. If you are still not convinced, I would urge you to start reading the book “Refactoring” and implement the refactoring techniques in your work. The advantages are many. The only challenge you may face is scheduling the refactoring work along with your other important work. For that, you can take advantage of the times when you will be doing code reviews or pair programming or fixing a bug. For every work you do, try to think about how you can introduce refactoring. Your present teammates, people who will work on your code in future, your customers and most importantly your future self will thank you.