Refactoring very dirty, 1000+ lines of procedural legacy code, without underlying unit tests at hand is one of the most dangerous programming activities possible, and as such often it is not touched at all. Today, I would like to introduce you to a methodology I use in such cases. Before being able to write tests for it, you would have to understand it, which, for nasty legacy code, often is impossible (within reasonable amount of time). My first goal therefore is simply to understand the code. I start by looking for the people in the team with the deepest (business) knowledge of the code, where I would often face further political barriers “this code is fine and does not need to be touched…”.
With extreme finesse and even more patience, it should be possible to win these colleagues over and make them explain the legacy method to be refactored. If not / if the explanation is not sufficient, I start with even more finesse to touch the code, only by using Eclipse auto refactoring, like method / variable name refactoring. Changing the order of methods inside a class, introducing static variable names for magic numbers, and most importantly, the automatic “extract method” feature.
I usually do this in several iterations, whenever I have spare time at hand – for complex code this situation can continue for months. At first, the code might look even more complicated, but extracting more and more sub-methods and extracting more and more magic numbers, over time, will help to better understand the code. Facing your colleagues with your new gained insights, will often lead to further and deeper breakthroughs. When finally, you (almost) fully understand the code, you will have to decide whether you want to continue refactoring, or if rewriting the entire code is the more economical solution. Often, I decide for the later, and rarely had to regret it. When starting from scratch, your creativity can spread freely, and you can start in a unit-test driven mode, which will not only improve the code but also add the still missing unit tests.