Adding features to an old code base is hard and often not much fun. It is especially hard when not enough time could be budgetted to really get to understand what that particular piece of code is trying to accomplish, let alone to figure out by which coincidence it is actually almost accomplishing that original goal most of the time.
But of course, if you want to stand a chance of successfully shoveling all the 'accidental features' that you and your teammates introduced in the previous release candidate under the carpet, at the end of the day you need to get pretty familiar with whatever logic apparently appeared most intuitive to a bunch of other clowns.
So this week, after spending hours doing my very best to avoid making 'new major changes', which many of us claiming experience with such matters consider risky at the project stage we're in, I had to concede that I didn't really understand much of what some esteemed predecessor had thought was a good solution to the problem at hand. And if we wanted our users to enjoy working with an application that behaves in a somewhat predictable fashion, the last programmer leaving his mark should at least be able to predict that behaviour rather precisely from what he'd observed. As it was, all of us unlucky enough to have witnessed that particular string of characters were manically trying our best to eventually forget that painful sight.
Coming to realise that there would not be any other way out apparently was the hardest part. Finally, yet another unexpected 'accidental feature' side effect broke what was left of my resistance and I set out to do what we had all agreed by oath to never do... With a next release candidate scheduled for yesterday (or the day before), I was going to seriously touch untouchable code... I started to slowly replace all kinds of magic numbers with self-describing semi-constants (say what?) and flattened deeply nested if-then structures by introducing just enough well defined boolean variables. Eventually a satisfying sense of logic started to emerge... Even the readable and predictable kind of logic that I was looking for! But then, with the spaghetti straigthened out and all alligned, and some initial testing confirming that the program was actually doing what I now believed it should, the scary thing was that quite a number of lines appeared to be missing in action...
Not to worry though! Let's just say "less is more" and 'what he says' etc. etc. and hope nobody is going to actually, you know, miss those lines ;-).
And if you think that I am completely full of myself because of my little far fetched success story... well, you might be right, but I tend to consider this more of a humbling experience really. And don't forget that I now have many boring hours ahead of testing just about all the different scenario's the code attempts to deal with... which was probably the real reason I was putting off this refactoring for so long in the first place. And, err, no, unit tests were not exactly available or straightfoward to introduce in this 'JSP heavy' environment.... :-(
Anyway, what I enjoy about this is that dealing with legacy code can actually become rather satisfying and good fun as soon as you dare fixing things up, even in small ways. That, and that it gave me an excuse to link to a great blog post that advocates keeping code bases small, but loses all credibility by being way too long itself... :-)