Refactoring is the process of changing a software system in such a way that it does not alter the external behaviour of the code yet improves its internal structure.
Martin Fowler
I believe that sometimes code needs to be refactored. For example, an improvement in the internal structure of a software system is sometimes necessary in order to improve its extensibility. All too often however refactoring is taken to mean ripping out the guts of the system and starting again. It is a common problem that programmers will try to make the move to cleaner code by throwing out the existing body of work and beginning from scratch.
To be effective refactoring needs to be understood for what it really is. There are a couple of keys to effective use of refactoring in a project:
- Refactor in small iterations. After each iteration the external behaviour should be the same.
- Check that the external behaviour remains the same! This is where you run the test suite. You do have one don’t you?
- Modifying or adding functionality is not refactoring! They are separate steps, keep them separate (using small refactoring steps reduces the temptation to merge these different processes)
Without rigorous testing of refactored code can you be sure that the code is functionally equivalent? If you are “refactoring” code and not testing it then you are potentially introducing bugs for no external benefit! I am reminded of a quote from Lou Montulli:
I laughed heartily as I got questions from one of my former employees about FTP code the he was rewriting. It had taken 3 years of tuning to get code that could read the 60 different types of FTP servers, those 5000 lines of code may have looked ugly, but at least they worked.
You cannot refactor code if you do not understand what its external behaviour is. When you perform refactoring in small steps with frequent testing then you will begin to get the benefits from it. Two key insights to refactoring are:
- It’s easier to rearrange the code correctly if you don’t simultaneously try to change its functionality.
- It’s easier to change functionality when you have clean (refactored) code.
I cover this subject today because of a discussion I was involved in concerning the CSS property visibility
and its value collapse
. In investigating the situation with respect to the rendering of these properties I discovered that it was rendered incorrectly in a variety of browsers. Investigating whether this had been brought up in bug tracking system of the mozilla project I came across bug number 77019. The problem had been identified, reading the comments on the bug I came across this beauty of a comment:
Oh Noooooo, we had the collapse code working in the tree for years and it was simply optimized away. Hmm may be optimized is not the correct word for it.
And here lies the moral of this tale, refactoring without understanding the existing code or without rigorous testing equals the introduction of both regressions and new errors into the software system.