Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior.
Usually, when writing code, developers deal with deadlines, delivery stress, and very specific feature descriptions. The main concern for a developer should be to deliver the needed feature on time and with the least possible bugs.
Revisiting the source code, after building those features, a developer would notice some redundancy, some code written in the wrong place (not following the design pattern).
So What is Refactoring?
Maintaining the same features, the same functionalities, refactoring is all about restructuring the source code. It can be consolidating common code per functionality or segregating code into many singular responsibility functions.
In other words is writing the same code, in a better design and structure that makes it more readable, testable, and maintainable. On a more visible account, the solution can be more performant with good refactoring.
Refactoring is done in small operations, transforming the base code. The result of a sequence of these operations produces a significant change in the code.
Keeping the refactoring operations small, make it less likely to introduce new bugs or main dysfunctionalities or even to break the system. having unit tests and integration tests in place helps make sure the refactoring isn’t breaking the system.
When to Refactor?
As we said before, refactoring should be a small operation, and to be able to keep it small it needs to be part of the day-to-day operations for a developer and it also should be clearly stated in the project plan.
Every time we aim to add a new feature, we have to study the structure of our existing code and check if it is ready for the new change. refactoring the base code first, in preparation for the new addition makes it faster to implement the new feature and results in a better-shaped code.
The same applies after adding the new feature, if we take a look at the code we would notice it can be clearer and more structured.
What should we do? Refactor again.
Always investigate your base code, before attempting a new addition, because whatever you need to do, might be coded somewhere in your solution, and you can simply refactor, and reuse it.
Refactor often and always
To add to what we said before, keep your refactoring a group of small operations, as refactoring is not a goal on its own.
It is not about fixing bugs
Refactoring your code is not an opportunity to fix bugs. Keep your focus on the main purpose of the refactoring you are doing.
Maintain consistency in your code
Similar to handwriting, every coder have a style. Keep in mind that having different styles in the same code base makes it harder to read, debug and to understand.
A good practice in code refactoring is to follow specific rules to keep the style homogenous and consistent throughout the solution code base.
Get rid of code duplicity
If it has been developed, no need to code it again. Read your code, and find duplicate functionalities. Then choose how to handle them in one function that can be called across the application.
Test, always test
Test early and test frequently, while refactoring. Code refactoring shouldn’t be a source of new bugs nor new features.
Keep up with your tests, make sure the refactoring is not changing or affecting your expected outputs and you will be in a better place after you are done with your refactoring exercise.
Refactoring with a different goal in mind
keeping your source code tidy is not always the goal of refactoring. Yes, we want readable code, structured code, consistent code. But more importantly, we want a functional and performant code.
As it should be clear by now, there is no single correct way to achieve a certain result in coding. it is also wise to code a feature the easiest way possible make sure it works and it is achievable, then refactor it into the better version of it.
At the same time, sometimes we develop something that works well but after a while, for a reason or another, it under-performs; That's also an opportunity to refactor.
Different data structures performs differently with different algorithms, and sometimes we might choose a data structure that works well at first and then it stops performing the way we need it to.
refactoring what data structure to use and how to use it in a specific scenario can affect our solutions performance immensly.
Querying the database, either with simple SQL queries, or using ORMs like ActiveRecord, can be very straight forward and it can get really messy.
Many different reasons can affect the way our queries perform, I am not going to dig deeper in that subject at the moment, but what we need to keep in mind is that refactoring our queries while still returning the same records and the same results, can perform way better.
For a specific task we need to be aware of how many queries are we sending to the database, which can have very different performance results with the DB being on a different server or on the same server.
Do you need all the data you are querying? if not why to overload your solution.
What to keep in mind!?
Refactoring is an ongoing process that happens in parallel with coding to keep the base code tidy, readable, testable, and maintainable.
Sometimes extra refactoring can be needed for performance issues.
Anyway, make sure to keep testing your solution, while refactoring to make sure your changes aren’t affecting your expected functionalities nor results.