We’ve recently released the latest version of our product. A relatively minor change – just a couple of months dev plus same again in QA. As we get closer to the release date, we’re less inclined to make major changes to the codebase. Unit tests or no, it’s just not appropriate to perform major refactor work in response to a bug report the week before release. So we tiptoe round the code, tweaking this and adjusting that with only one eye on how maintainable it will be in future.
For example, a few days before release I found that a few text fields on a web form were completely redundant. Whatever they wired up to has been replaced by something that can work out the value for itself. Should I have removed the text area? I was 99% sure it was safe to do so, but I must have made judgement calls like this 80 or 90 times in my career. I’m due to get one wrong soon. And the consequences would be another phase of QA, making the project late or (worse) releasing a broken product.
The result of this is that beautifully designed code is written during the dev phase, it’s carefully rationalised and refactored. Should anything be found not to hang together quite right during QA, out comes the gaffer tape.
There is absolutely nothing wrong with gaffer tape so long as its understood to be a temporary solution. If the wing mirror falls off your car, stick it back on with gaffer tape. That way you can safely drive home, remove it, fix it, replace it. It may well function as a mirror when it’s held on with gaffer tape, but it’s still broke.
Same with the product code. It may well do the job it was intended to to and it may well pass UAT, but it’s still broken and is in need of repair. Otherwise you apply gaffer tape on top of gaffer tape on top of string on top of glue. Then as soon as you want to change something (it’s software, someone will want to change it) you have to unpick all your patches. And once you remove all the patch code, you’ll find there’s nothing left underneath. The nuts and bolts of the design no longer holds the system together. Nothing holds the system together, except possibly static electricity. You may well be able to stick a balloon to a wall with static, but I wouldn’t try hanging shelves off it.
I have worked on my share of over patched systems. I’ve had some wonderfully instructive archaelogical digs through layers of code. You can dig down through the worst code, working backwards through revisions and eventually find a reasonably well designed, carefully planned system. You get from one to the other just because people don’t clear up their mess.
When I started work on a new system about two years ago, I had this at the back of my mind. I was quite pleased with the overall design of the system at version 1.0. But I was aware that it would turn to mush unless I was very careful. I’m lucky enough to have a developer (rather than a manager or salesman) for a boss, so I can usually persuade him that it’s in his interests to allow a week or two between versions for tidy ups. A little time spent refactoring, cleaning and removing dead code can save dev time (and certainly bug fix time) later. This is the sort of thing that’s very hard to explain to salesman bosses. By the usual definition of refactor, you’re not adding any new features. You’ve spent a fortnight making the sytem behave exactly as it always did. That’s quite hard to sell. You can be sure that customers won’t pay extra for it.
I’ve always considered a day when my net lines of code is negative (that is, I’ve removed more than I’ve added) to be productive. It’s certainly satisfying. The benefit is hard to quantify. Broadly though, the number of full time employees required to maintain code is proportional to the number of lines they maintain. Put another way, when you remove stuff, you can work on what remains more efficiently. You won’t necessarily notice yourself working faster. You will find however that estimates are more likely to be wrong on a bloated, poorly maintained system. You will estimate how long the change should take to complete and then find it takes longer. An hour here and there trying to work out the tortuous logic. The odd half day investigating some tricky concurrency issue. It will add up.
So remember what your grannie said: A stitch in time saves nine. Prevention is better than cure. A swan can break your arm y’know.