When in doubt, Refactor (or, the Blind Man and the Matzo)

Have you ever "inherited" code written by someone else, usually somebody who doesn't even work there anymore, and been told to "Make it do X"? And you look at this code and it is UGLY! It's so ugly it could scare the chrome off a bumper! Not only that, you can't even figure out what the hell it does! This code is like the blind man and the matzo. (Joe takes his Passover lunch to the park. A blind man comes up and sits down on the bench besids him. Joe, feeling neighborly, hands the blind man a sheet of matzo. The blind man handles the matzo carefully for a minute, then looks up and says, "Who wrote this CRAP?")

Well you have three choices, usually:

1) Add more spaghetti code to it, attempting to make it do "X", which it was probably never designed for.
2) Refactor.
3) Quit and go work someplace else, with no guarantee that you won't be jumping from the frying pan into the fire...

What is Refactoring?

Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior. The general idea behind refactoring is to make a series of small changes, in such a manner that the "System" keeps functioning after each change. Each change is supposed to make the code more manageable, easier to understand, and easier to extend and re-use.

However there also exists a "broader definition" (although it isn't the "official" one), and that is to refactor / rewrite code. Usually what this means is that there are "too many pieces" tied up in one class, and because of this complexity, it has become difficult or even impossible to do the "spaghetti code thing" to it in order to get it to do "X" (which of course, remember, it was never designed to be able to do in the first place.) You can usually tell that you need to do an "RR" (refactor / rewrite) when you are forced to put in a lot of conditional "if / else" blocks in an existing class in order to make it "jump over" blocks of legacy code when a certain "new condition" that you have added to the class is true. Another hint is when you see methods in there that, to any logical mind, should not be "locked up" inside this class; they should really be in their own separate class (Occasionally you can do that XP thing and "Smell the code". If it stinks, it usually means you've got some old data in there that's gone bad-- another reason to refactor).

Generally speaking, what you want to do in this case is to break out the various methods and or fields that really don't belong there under your "new vision" (which hopefully is a bit more inspired than that of its predecessor) and put them in separate classes that can be referenced by the code in the target class of the refactoring effort. And you want to do the classic "small step" refactorings too. In some ways, refactoring is like database normalization.

Refactoring, like other techniques, has been reduced to a science, and there is a lot of published information on it, which I won't bore you with here. The two key words are "disciplined", and "technique". Suffice to say that the Microsoft folks thought it important enough to put it into Visual Studio.NET 2005. Oh, it's far from a complete implementation, but there are some pretty good basics they managed to get in there.

Another big advantage of making decision number 2 (from above) early on in your effort, is that it forces you to "learn while doing" -- in the process of your refactoring, you will actually begin to understand what the hell that nameless "predecessor developer" from whom you inherited this awful mess was attempting to do.

Bask in your new-found superiority. Refactor Mercilessly. Oh, and -- pass the matzos, would you?