Saturday, 30 March 2013

Software wears out

One of the things that non programmer friends often find hard to grasp is the concept that software can wear out and get old.

It should not happen - code is code - it does not change on its own, how can it wear out?

Well, over time, and I mean years of time typically, things happen.

1. For a start, any maintained system will undergo a number of small changes, more at first, but over the years there will be slight tweaks. In essence the requirements are changing subtly over time. This is not a surprise, requirements do change, and any business systems will have to move with changes in the business, and regulations and policies and so on.

Each change will be considered, and one of the decisions that has to be made is whether to start again, or modify the existing system. Each change is usually small enough that the right choice is a modification. This is normally from purely pragmatic grounds. Starting again takes time, costs money, and adds risks as all code comes with some bugs.

The problem is that over time the code becomes a complicated mess with sticking plaster on top of sticking plaster. It may have started with an elegant and easy to understand design, but over time that is lost.

In some cases the original requirements lead to a design that simply does not fit now, so the code is doing it the wrong way, but with work-arounds to make it work.

You also find that comments and documentation are not quite up to date with all the changes, so it makes it hard to follow.

2. As a programmer, you change. Even now, after over 35 years coding in almost every language you can think of, I still find myself learning better ways to code. I have also built up a load of my own libraries which are used extensively in the business, and these are themselves programming projects which get old.

This means you look at old code, even code that has had no patches or changes, and just think "what idiot wrote this - it is messy", and it was yourself, a year ago.

3. Bits of code become obsolete over time, as the code and the requirements changes, but you end up with code that nobody knows why it it is like that. You can see special cases added in a panic to fix something that was broken and serious, and you know it was special and important at the time, but is it still needed? Thankfully good commenting and source control help with this, but even so, you still find the one line change you committed years ago, and can't understand the explanation you logged now. You have no idea if it is safe to remove this special case or not.

With all of this in mind, some times, you just have to start again. Making a new specification of what is actually needed, and trying to incorporate any special cases that exist in the current code - or at least understand why they are not needed.

This month we did that with one of the most important parts of the business - the BACS payments and collections system. It all started because we had to change the last step - sending to BACS - as Lloydslink was closed down. We could have just bolted on an extra sticking plaster to convert the Lloyds files to a new format, and indeed, that is what was done for the initial testing. However, the more I looked, the more I pulled at this thread - and found "worn out code" in place.

The result is all new code, using current versions of all my libraries, and a style of coding that is much better than before. It has all of the features we need, and at least one that I had missed (ooops). It is faster, more efficient, and easier to maintain with more comments.

Even so - in a year's time it will look old again, and you can bet some requirement will have changed and some patch applied.

With all of that said, I have to say that it is very rewarding rewriting something like this, if you can find the time and motivation.

One of my real programming jobs, when I worked for a mobile phone manufacturer, meant re-writing other peoples old and worn out code, and I had great fun capturing the real requirements, making a new and elegant design, and coding it in half of the previous code space (we were short of RAM and EPROM for this project so it was needed). It was nice to make things "work better" and be cleaner code. This was not a slur on the previous programmers - if it was my own "old and worn out code" it would have been the same.

At the end of the project the team leader had to complete a report for management and so he got stats from the source control system - including how many lines of code each of us had done. Turned out I had not only coded many times more lines of code than anyone else on the project, something which does not surprise me at all, but I had deleted a hell of a lot more lines of code than I had added. The team leader refused to report this as a huge negative number, for some reason. Shame, I was hoping to break someone's brain with that in senior management. Those were real Dilbert days...

7 comments:

  1. I write programs for PLCs (programmable logic controllers for automated machinery) and this sounds all too familiar. As you say, it's bad enough reading your own code after 12 months, let alone others. And code grows organically, as you end up adding a patched solution rather than the recode it requires as you don't have the time.

    ReplyDelete
  2. Excellent post. I rather wish you had posted this a number of months ago and posted it to SMT at RBS Group prior to their gargantuan mistake involving CA 7 batch files. Perhaps if your well articulated point was made to management teams, they would actually understand the importance of maintaining their software in order to reliably serve customers and their own customer facing staff.

    ReplyDelete
  3. Where does today's Firebrick sit, in the cycle of code replacement?

    ReplyDelete
    Replies
    1. Excellent question. Still quite new and shiny code, but some modules are being redesigned form scratch, like the RADIUS client code, because of requirements changes. Very keen to avoid lots of sticking plasters.

      Delete
  4. I'm in the middle of a rewriting project for a 10 year old project right now (that for too long was patched with 'quick fixes' and is now an impenetrable mess).. it's a nightmare, because we have to keep selling it so can't just throw it away and start again.

    It can be hard to impress on management the necessity of small rewrites to avoid a huge, expensive one down the line. Ours learned the hard way.

    ReplyDelete
  5. I converted a program I helped my father write, from one dialect of BASIC to two others. As I did, I improved certain routines, in some cases by completely rewriting them, and put the changes into the original dialect as well. My father was surprised, as he thought he'd written good routines. In testing, mine proved faster, even if less clear. One particularly poor routine in the original that was improved in the conversion was in fact a part I originally wrote. A rewrite, to the original design, took up much less space and worked a lot faster.

    ReplyDelete
  6. > you still find the one line change you committed years ago, and can't understand the
    > explanation you logged now. You have no idea if it is safe to remove this special case or not.

    But the test case you wrote before you made that change should make it clear, right? ;o)

    ReplyDelete