"The idea that new code is better than old is patently absurd. Old code has been used. It has been tested. Lots of bugs have been found, and they've been fixed. There's nothing wrong with it. It doesn't acquire bugs just by sitting around on your hard drive. Au contraire, baby! Is software supposed to be like an old Dodge Dart, that rusts just sitting in the garage? Is software like a teddy bear that's kind of gross if it's not made out of all new material?
Back to that two page function. Yes, I know, it's just a simple function to display a window, but it has grown little hairs and stuff on it and nobody knows why. Well, I'll tell you why: those are bug fixes. One of them fixes that bug that Nancy had when she tried to install the thing on a computer that didn't have Internet Explorer. Another one fixes that bug that occurs in low memory conditions. Another one fixes that bug that occurred when the file is on a floppy disk and the user yanks out the disk in the middle. That LoadLibrary call is ugly but it makes the code work on old versions of Windows 95.
Each of these bugs took weeks of real-world usage before they were found. The programmer might have spent a couple of days reproducing the bug in the lab and fixing it. If it's like a lot of bugs, the fix might be one line of code, or it might even be a couple of characters, but a lot of work and time went into those two characters.
When you throw away code and start from scratch, you are throwing away all that knowledge. All those collected bug fixes. Years of programming work."
I find what Joel says problematic - firstly, you touch that code and you might break something, so it's fragile already, and secondly if it dealing with corner cases, then it should be documented.
This accurately catches the reasoning behind my approach to testing though. When you fix a bug, write a test that reproduces the bug first. That way, when someone tries to refactor the messy code, they'll know that they broke something that was causing a real big.
I generally try to have two type of test: nominal "happy case" tests that verify basic functionality of modules when used in a normal way, and bug fix tests that are labelled as such, with a reference to the bug in the bug tracking system. So now when you see my warty code and try to clean it, the test fails, and you can even find a description of the original problem that the warty code addresses. Now you know that you either have to find a cleaner solution, or just leave the warty code alone.
This system means that most of the tests I write are targeted at things that really cause bugs, not just busy-work testing of things that would never go wrong, but rigidify code bases (the more tests you have, the more you have to modify when refactoring, and how do you know if the test or the code is wrong during the refactor???)
Should be an the real world do oftentimes just not match.
Clearly these cases should be clearly marked, but how often do you encounter these undocumented remnants of lost institutional knowledge. What Chesterton would imply here is to try to understand what these do and after doing so maybe deciding on a better way - even, if this means just documenting the stuff.
I feel like there's also a lesson here on the importance of commenting. If all of those inexplicable hairs had been properly commented, you wouldn't have to wonder.
On that note though if you compare the old code to say a water pipe, the old code could be a pipe with tons of duct-tape over every leak and a new pipe could in fact be a good choice. It's not always a great idea to rewrite from scratch but it isn't always the best to keep old code around either.
http://www.joelonsoftware.com/articles/fog0000000069.html
"The idea that new code is better than old is patently absurd. Old code has been used. It has been tested. Lots of bugs have been found, and they've been fixed. There's nothing wrong with it. It doesn't acquire bugs just by sitting around on your hard drive. Au contraire, baby! Is software supposed to be like an old Dodge Dart, that rusts just sitting in the garage? Is software like a teddy bear that's kind of gross if it's not made out of all new material?
Back to that two page function. Yes, I know, it's just a simple function to display a window, but it has grown little hairs and stuff on it and nobody knows why. Well, I'll tell you why: those are bug fixes. One of them fixes that bug that Nancy had when she tried to install the thing on a computer that didn't have Internet Explorer. Another one fixes that bug that occurs in low memory conditions. Another one fixes that bug that occurred when the file is on a floppy disk and the user yanks out the disk in the middle. That LoadLibrary call is ugly but it makes the code work on old versions of Windows 95.
Each of these bugs took weeks of real-world usage before they were found. The programmer might have spent a couple of days reproducing the bug in the lab and fixing it. If it's like a lot of bugs, the fix might be one line of code, or it might even be a couple of characters, but a lot of work and time went into those two characters.
When you throw away code and start from scratch, you are throwing away all that knowledge. All those collected bug fixes. Years of programming work."