- I get some requirements for a program from my boss or a client.
- I write the program as perfectly as I can.
- I test the program with all the cases that I think it will need to handle.
- The program is done and people start using it.
- For whatever reason the requirements change (or a bug is found), and I have to go back and modify the code. Inevitably less testing is done on these changes than the original writing.
- Go to #4.
It’s pretty rare for the original writing of a program to have a significant bug in it after testing, although I’m not perfect. Almost all bugs are introduced in step #5. When you first write the program, the entire program and its relationship with other programs is in your mind. But when you go back to look at old code, it’s just not fresh in your memory, and it’s very easy to make a change without taking into consideration all the consequences that change will have.
Sometimes when I’m doing testing on change to a piece of code, I’ll find a problem in an unrelated common part of the system, like a line of code that is run several dozen times every time anyone goes to any page on any of my company’s websites. Looking at the code reveals that there is no way this could possibly be working, and yet millions of dollars of revenue have been earned specifically because that line worked.
What is really mind-blowing about Schroedinbugs is just how often they occur. I find bugs like this several times a year. Today was one of those days.
I have to wonder if other branches of engineering have similar phenomena. Do engineers sometimes find a rusted bolt and say, “Man, I can’t believe the bridge is still standing!” Do doctors often tell patients, “According to medical science, that really should have killed you.” I certainly hope not, but my intuition tells me it happens all the time.