Please note that I don't update this web site anymore. You can visit my new personal blog at www.williamwilling.com.
Never Rewrite Code From Scratch
Friday, April 15, 2005
At the beginning of this week, I made a mistake that's very familiar to me. I want to be able to add new puzzles to Trichromix after its release, so that I can sell additional puzzle packs. Also, players should be able to share their own puzzles, so installing a new puzzle should require a minimum amount of effort; I'm not exactly targetting computer whizz kids with my game. To make this possible, I had to make quite a few changes to the code that manages the puzzles: loading, saving, remembering if puzzles are solved, that sort of thing.
If you can remember how the Trichromix code base came about, you'll probably understand that digging around in it is no picknick. So, I decided to start a new project and create a PuzzleManager class. Writing the puzzle manager didn't take long and the code looked very pretty. Alas, integrating it into the existing Trichromix code wasn't trivial and this is where I went wrong: I decided to rewrite the framework (graphics, input, game states) so it would work well with my new puzzle manager.
Let me give you a little advice here: you should never rewrite existing code. It doesn't matter how ugly you think your current code is or how much prettier the architecture is that you have in your mind now. Rewriting code is bad. No, it's worse than bad: it's evil!
The first time I made this mistake is a couple of years ago on my first paid programming job. A friend and I earned our money by writing custom web applications. Microsoft's .NET Framework was still in beta, but we were already using it with great zeal. Our first application was an electronic learning environment that supported project-based education and was fully tailored towards the educational methods used by our customers. It was a great first assignment and with my passionate interest in education, I was more than happy to do it.
After about four months, we had a working prototype and a group of guinea-pig students to subject to it. The general response was that the application was promising, but that it still lacked a lot of necessary features. Since it was the end of the schoolyear by now, we had two months to add the wanted features and prepare the application for prime-time use. So what did we do? We rewrote the learning environment.
The new code base was much prettier, the user interface was better, new features had been added. Hurray, right? Wrong. There is no way you can explain to a customer why some functionality that was there two months ago, is suddenly gone. Of course, the truth is that at the end of the two months, we couldn't meet our deadline, so we had to drop some features, even though they had been present in the old version. The features were non-critical, but teachers still expected them to be available.
That wasn't the worst part, though. The rewritten version had a bug. A serious bug. Every once in a while the application would slow down to a crawl. When this happened, it became completely useless and since every student and every teacher depended for a great part on the learning environment, this was a Really Bad Thing. It took us seven months before we could remedy the problem. We never found out what the cause was, but after arduous attempts we finally stumbled across a fix.
The learning environment isn't in use anymore. Although the reason for discontinuing its use presumably had nothing to do with our failure, I think that our product would still be supporting teachers and students today if we had just delivered the valuable tool we set out to create. Afterwards, I made a list of all the mistakes we'd made during the project and at the top of the list, with distance, was: it was a huge mistake to rewrite the application. I decided never to make that mistake again.
When I realized how many 'little things' I would have to program anew if I were to start Trichromix from scratch, I took the afternoon off. The next morning I attacked my 'old' Trichromix-code and refactored it until I could make the changes I wanted to. It took me three days before I realised I was making my old mistake again, but fortunately I had the good sense to backtrack. Writing the entire game around the new puzzle manager is like buying a new suit to fit your tie. It might be tempting when the tie is really cool, but it's a lot cheaper to just find another tie if your old suit still fits.
Never rewrite your code. Joel Spolsky agrees.
"Chronic remorse, as all moralists are agreed, is a most undesirable sentiment. If you have behaved badly, repent, make what amends you can and address yourself to the task of behaving better next time. On no account brood over your wrongdoing. Rolling in the muck is not the best way of getting clean." -- Aldous Huxley
Back to blog index
There are only a few reasons why one should rewrite the entire code:
- Hierachy is wrong
- The base you have been working has been changed (like porting from PC to console)
For all other problems you must cheat, code dirty, ignore problems. Those things come when the product is finished. Than you may start on the most annoying thing and that is cleaning your code. Removing old code, optimizing, remove duplicate code. More annoying than cleaning your room.
Monday, April 18, 2005 7:04 PM
I can't say I agree with you. No matter how wrong your class hierarchy is, you're better off slowly resculpting it and moving code around than you would be rewriting it. It's a labourious and boring task, but in the end it's the better choice.
As for porting to another platform: if you expect your project will have to be ported sooner or later, you'd better abstract all platform-specific code. If you haven't designed portability into your project and you still have to port, then you will have to change your design and that brings us back to changing the class hierarchy.
Also, I wouldn't recommend waiting until the very end to clean up your code. The reason I was tempted to rewrite Trichromix, was because I let the code base 'rot'. What I do nowadays is add a bit of functionality until it works to my satisfaction and refactor immediately afterwards. These two tasks combined usually don't take more than a couple of hours.
The act of cleaning up might not be fun, but when you're done and you look at the result, there is this feeling of satisfaction that makes you forget the amount of work it took. The more often you clean, the more often you feel satisfied and the less cleaning you have to do each time.
I'm sure your mother told you something very similar many times while looking at your room; put your stuff back after you've used it, place your dirty laundry in the laundry bin, clean up now so you won't have to do it tomorrow. She was right and if she had been able to read your code, she would tell you to clean that up often, too. Such is the wisdom of mothers. ;-)
Tuesday, April 19, 2005 10:26 AM
Whoops... You're right.
I only rewrote the entire CGame Class (which is 95% of all code). The Graphics, input, etc class were still from a old project. Not that it really mathers, but it makes me realize that my earlier statement wasn't etirly correct.
My mothers has given up on making me clean my room. But there is a reason why I don't clean up my room. After I clean my room I can't find anything anymore. When it seems to be everywhere I always know exact where I left my things. It maybe dirty but it as also fast, but on the otherside there is a chance you slip because it is dirty....
Monday, April 25, 2005 1:16 PM
At the risk of taking this metaphor too far, I'd say that your statement of finding things in the mess supports my argument.
What you do now is let your room get sloppier and sloppier. You know it's a mess, but it works for you; something that mothers never seem to understand :-). This is much like an ill-designed code base.
The one time in many weeks (or months) you do clean up your room, it's like rewriting code. You don't just move stuff around a little bit, you put everything in completely different places, creating an entirely different system of organisation. The result is that what worked before, doesn't work anymore. In your room that means that you can't find your stuff anymore, in a computer program it means that your stuff doesn't work properly anymore.
If you clean up your room at the end of every day, you don't have a lot of cleaning to do, you can always find your stuff and it pleases your mother. Similarly, if you refactor your code at the end of every day, you don't have a lot of refactoring to do, your code always (well, nearly) works as expected and that pleases your customers.
A little irony I'd like to point out is that I'm arguing here that bug-prevention is a major reason you shouldn't rewrite your code, while your mother may tell you that bug-prevention is a major reason you should reorganize your room. :-) Now I just know I have taken this metaphor too far...
Wednesday, April 27, 2005 10:38 AM
To come back at the metaphor (What? Again? ^_^ )
There is a difference between rewriting code and restructuring code. Rewriting means you don't clean up, but instead you burn the house and build a new one (O.o). While restructuring means you place things were they should belong and no longer leave things on the floor.
Offcourse when rewriting code you most likely restructure it as well.
But rewriting shouldn't be done often (you're not burning down your house every few months)
But to keep us from going on this subject (and allowing you to post another item) I will end it with this: "Don't burn down your house, when you haven't have another one." or "You can rewrite your code but only when you can do it and have time for it. and don't use it it untill you have complety finshed it. Untill then use the old code"
Wednesday, April 27, 2005 2:00 PM
Sorry, for the above post. It says Anonymous but it was me (Wouter Lindenhof)
Wednesday, April 27, 2005 2:01 PM
Tell me what you think
Since I'm not updating this site anymore, I disabled comments. You can visit me at my new site: www.williamwilling.com.