Code refactoring is the process of restructuring the previously written code without changing the code functionality. Refactoring does not mean adding new features or re-writing code to fix any kind of bugs.
There are several benefits of doing refactoring, which include:
Usually, refactoring is done for small chunks of code at a time instead of dealing with a huge codebase directly.
Don't forget that there should be a well-written test case before refactoring. Test cases help to ensure that the newly modified code does not break the existing feature. It is also a good practice to test the overall code coverage of the application from time to time. There might not be 100% code coverage, but engineers should always aim close to 100% code coverage.
The below diagram shows how the refactoring process is usually carried out.
I want to share my own story regarding how my team and I dealt with refactoring in the past. I have worked on various projects over the five years. One had a very old codebase which was challenging to maintain and scale. We came into a situation where we struggled to add even a minor feature.
There were lots of code redundancies. We discussed this issue with the project CTO and product owner and agreed to perform refactoring before adding any new features. Jumping directly to modify the code was not an option since there were no test cases written.
When our team decided if we should refactor, we considered refactoring at the following developer workflow steps:
Code review, also known as Peer code review, is a process where code reviewers check the codebase before accepting pull requests. It is a great way that ensures the code is bug-free, efficient, and follows the best coding conventions.
Adding every team member as a code reviewer helped us to find bugs early and maintain a consistent coding style across the company since the PR would be merged only after all code reviewers approved the PR.
One of the ways to consider refactoring is before adding new features or any changes to the application. Doing this will help to improve the codebase of the application and is more efficient to use by future engineers. Also, engineers should regularly check if the project has good code coverage.
Since our application was written using Ruby on Rails, we used Rubocop, a Ruby code style checker (linter) and formatter. Rubocop automatically fixed some problems as well as reported problems in the codebase.
Usually, most startups aim to launch their products fast. There might be some code that does not meet the high code quality standard in this process. So, refactoring the codebase once they have the market fit is also an excellent way to make code more efficient and robust. Doing so would not slow down the business since the product is already launched in the market.
Our team used this approach for refactoring since the product was already launched in the market. We worked on refactoring most of the application's codebase to improve code readability and reduce complexities.
There are lots of challenges that startups face while doing refactoring. We faced many issues while doing so, which I would like to share below:
Sometimes, refactoring takes a longer time than expected. Startups frequently need to add new features and are more focused on bringing products to the market as early as possible. Startups would need to hire a dedicated developer or hold off working on new features and perform code refactoring.
We dealt with the legacy codebase without any test cases, so it took us way longer than expected.
There are always some chances of introducing bugs while doing code refactoring. Engineers need to understand the code logic before refactoring the code properly.
This process helped us track bugs in both staging and production environments.
Refactoring previously written code is a complex task to do. It becomes more complex when there are multiple developers or freelancers involved. First, you will need to understand the codebase and check if proper test cases are written or not. If any test cases are missing, it needs to be added. Understanding written code, writing test cases, and ensuring no feature gets broken by the newly modified code makes the refactoring process complex.
After a few discussions, our team decided to follow the following steps while dealing with refactoring:
We continued this process until the overall project was easily maintainable and had better performance.
We followed some of the below strategies to avoid or reduce time spent on refactoring:
One of the ways to reduce time spent on refactoring is by having a refactoring week every other sprint. Doing so will help to find issues with the codebase before it causes a huge problem, assuring that there won't be any technical debt in the future.
Using this approach, our team reduced most of the time spent on refactoring. We started writing missing test cases, which helped us to improve the whole code coverage.
Overall, having a refactoring week every other sprint is to reduce the time spent on bulk refactoring and prevent technical debt from occurring.
Developers spend most of their time on code editors. So the best place to flag these issues is in the editor.
Stepsize VSCode and JetBrains extensions help provide full visibility on the codebase issues that developers can solve before resulting in massive refactoring and technical debt and save devs countless hours.
You can link your technical issues to code linked to your code and see them in different project management tools like Jira, Asana, Azure DevOps, Linear, and many more.
After every coding sprint, it is always great to have a regular technical debt discussion. The team can discuss what went right and what didn't. Engineers could get healthy feedback through this.
We started having short technical debt discussions after coding sprints. After spending too much time on refactoring in the past and understanding the major consequences caused by it, product owners are also involved in the technical debt discussions virtually. It made them aware of the wins as well as the issues which need to be taken care of before it creates a massive impact on the project.
Refactoring itself is a very complex and frustrating task to do. Implementing the right process for managing technical issues and using proper tools, like Stepsize, helps avoid and reduce time spent on refactoring.