Refactoring is in general restructuring the code without changing its behavior. The key point here is the behavior because we need to make sure that the behavior remains the same after the refactoring. How do we make sure the behavior stays same: tests. Tests make sure our system or component behaves as expected under certain conditions. When we have tests in place then it’s easy to do the refactoring since we have some validation in place. Nevertheless, having tests in place is just the happy path. Let’s go over a more challenging path.
We will first create a scenario. Your manager throws you into a legacy project. Nobody knows how the project works and there isn’t much documentation either. So, what do we do? Quit? Sounds like an idea but no. All we need to make sure is that the behavior remains the same. Yet, this is very challenging when you have little information. Where do we start? Testing and again testing.
The first type of test that we will employ is the smoke tests. Smoke tests are very good to show that most crucial part of the system behaves as expected. We should add smoke tests as a build verification step to our deployment pipeline(Create one if not exists). Once smoke tests are in place, we will be confident that we won’t break anything terribly. The second important part is the knowledge. Once you construct the smoke tests you would understand the system much more.
Our next testing strategy is the unit testing. Employing unit testing would be much harder. However, it should be a step by step process. You can’t write unit tests to every single component. Also, it’s not really wise to write unit tests for all components because you will soon refactor it. Hence, we need to make sure that the core components behave as expected. What’s next? Choose a core component and start testing. Writing unit tests will automatically refactor the legacy code a little bit. What’s more, you’ll understand the internals of the project much better.
After applying these strategies we won’t have any untested code so the nightmare is gone. One might argue that s/he doesn’t have time to do the testing. On the contrary, skipping the testing will hurt much more and more often in the long run. Thus, you should make the testing first and top priority before doing any refactoring. If anyone argues against testing, defend it; otherwise, you will fail harshly.
Dealing with untested code might be unavoidable. So if you are to refactor an untested code, then test it first. There isn’t really any better strategy. Skipping testing is just signing your surrender.