A month or so back I spent a hectic couple of weeks on a client job and have realised I'm now in a position to write one of those 'We reimplemented a piece of software originally written in language X using language Y and you won't believe what happened next' articles. Well, you may well not believe it but you can probably guess it, because articles like that are 10-a-penny and the reported results are always that some problem with the original code was solved in the most wonderful way. That problem could be speed, maintainabilty, memory use, lack of suitable job applicants, almost anything, but you can be sure it was resolved by the simple expedient of chucking out a load of code and writing some new code. The new code is invariably shorter and more expressive, somehow lacking the cruftiness of the old. The author invariably had lots of fun writing the new code, and often declares their chosen language to be their favourite. Frequently the article conclude with a little coda encouraging others to follow suit, or roundly insulting those so blinkered they choose not to.
This is not that article.
It is the case that I replaced a piece of production code, developed by several people over a number of months, in nine days by myself. The new code is visibly faster, in the way that people notice without having to run benchmarks and draw graphs. It's leaner too - the VM it's deployed to has half the CPU and a quarter of the memory of the previous version. It doesn't time out, exceed its memory quota, or crash.
I must be ace on the old keyboard, right?
Well, perhaps. But if there's any lesson to be learned here, it's that reimplementing a system is generally substantially easier than building it the first time round. In this case, a data access layer for a website, the existing code told me exactly which endpoints I needed to support, and which parameters they took. The productions logs told me which of those endpoints were actually being used, and with which parameter combinations. Almost straightaway, therefore, I knew where to concentrate my efforts, and what I could ignore completely. The existing code had a reasonable set of unit tests, which saved me the bother of having to come up with my own. I was able to look at the existing database queries, and translate them across into my new code. I could examine how the existing code had a addressed a particular issue and evaluate whether I wanted to bring that into the new code. I had the ridiculous luxury of being able to run up the old code and my new code side by side, poke them with the same requests, and compare the results, one with the other.
In short then, I benefited hugely from the fact that the system already existed. There was just a ton of stuff I had to think a whole lot less about, and quite a lot I didn't have to think about at all. Consequently, I was able to spend more of my effort thinking about the things that did matter, and the result, unsurprisingly, was less code.
While I rarely suggest an all-out rewrite, I did one here because I was asked to. The language I worked in wasn't my choice, it was the client's. The new code is quicker, not because of any special property of that language, but because I was able to look at the old code, see the inefficencies, and was given time and space to do something about it. If they'd chosen another language, the results would have been similar. Hell, if they'd chosen the same language as before, the results would have been similar. If I'd been left to work on the original code for the same amount of time, I probably could have produced something similar1.
Even when you're throwing it out, there's a lot of value in old code. Be grateful for it.
1. Given their lack of faith in the existing code, I suspect that if I'd suggested just letting me have at it, I may well have been turned down. Had that suggestion been accepted, I probably would have only been given half as much time.