I fixed a bug today – a bug that was introduced because a chunk of code was depending on side effects of another piece of code to work properly. Depending on whether you’re ever worked directly with a computer language, this may be a subtle transgression, but the problem is distinct and real, and here’s the best part — if you learn why this is a problem, you’ll understand where this flawed thinking bites you in everyday business decisions, too.
So let’s back up and look at a non-programming example. Let’s say you go in to see you doctor because you’re feeling under the weather. The doctor runs some tests and sees that your white blood cell count is higher than expected. A good doctor would know very well that there are lots of reasons this can happen, but someone a little less disciplined who’s sitting at home playing “House, the Home Game” might shout out, “it’s cancer!” before really having any evidence to support their crackpot theory.
Most of the time, mistakes like this are lots more subtle, but they always start with someone seeing an effect and thinking they know the cause. Sometimes, we guess and we get it right, but often, we don’t.
How can we know when we’ve got it right? We need to relentlessly question the assumptions we make about the things we believe to be true. According to Alan Axelrod in his book, Patton on Leadership, Patton would frequently ask, “How do we know that?” His lesson is that we need to consider our sources of information, because some are intentionally misleading, others are unintentionally incorrect, and a few are reliable. If we can tell the difference, we’re doing well.
Instead of asking, “how do we know,” we could also ask, “why?” In a recent blog post, Joel Spolsky talks about his company’s use of the five why’s. Made famous at Toyota, and attributed for part of Toyota’s legendary quality, the Five Why’s are a structured approach to finding the root cause of a problem. In the case of a business problem, this might mean following a problem beyond our own department to uncover inter-departmental workflow issues, while in software development, this sort of root-cause analysis might lead us to find weaknesses in our architecture. The key here is not to stop asking questions when you get your first answer, because you’re probably still missing something important.
In the case of my bug, the code was checking the state of a variable, but the variable wasn’t a definitive indicator of the condition we were interested in. Rather, it was a variable the corresponded to the condition we were looking for most of the time. When this pattern changed, our code broke. The fix? Change our code to trap for the condition itself, not a coincidental side-effect.
Lest I lead you to believe that these problems are easy to spot, I’ll assure you that many aren’t. I’ve gotten caught a few times with the .Net framework, especially, when I’ve looked at the value of a .Net framework property while debugging and made assumptions about the general behavior of the property. By believing (falsely) that I knew how the framework was going to work, I left myself open to bugs.
Although it’s not easy to train yourself to think this way, a questioning mindset can pay off in a better understanding of things that are really true versus the things we merely believe to be true. There’s a world of difference.