Where do bugs come from?
People ask me: Are we ever going to get rid of bugs?
And I tell people: No.
And then they pull out their machine guns and things get messy.
But why is that? Are we really doomed for fighting bugs for the rest of our lives? Or theirs?
Are we never going to see the end of the shock of discovering “that’s not what I expected”?
Well, yes. And here are a couple of reasons.
We miss things.
We’re not perfect. It’s science. We can’t program for every eventuality, because we can’t think up every eventuality. That’s not just a programmer thing. We miss stuff in requirements, architecture, design, code, testing, deployment – any stage there’s a human involved, we’re going to miss stuff. And there in lay the bugs.
Even if we can think of all things that can happen, we need to communicate the ideas to other people. And it’s never a full translation of the picture is in my mind before I describe it to you, to the picture in your mind after that. Just last week I gave an exercise in my Clean Code workshop, and two people understood different things reading the same code. And code should be “the single absolute truth”. Prepare to be surprised.
We translate. Badly.
Since we’re talking about translation, there are translation error all around. from problem to solution, to design, to code. All these translation errors accumulate and wind up as bugs. But that’s not just errors in the solution and behavior. We also translate models.
These models are abstractions, so they drop details. Those end up as surprises. But even more so, we expect the models – the solution, the design and code models – to be similar. In fact if the model of the problem and solution is understood, we assume that the design and code will carry the same relationship.
Alas, no. Because code is elastic, we can define whatever model we want, free from any relevance to the “real life” model. It will work, until it doesn’t.
Here’s an example, again from my Clean Code class. There’s an exercise to build a Tic-Tac-Toe game. Almost everyone creates a Game class, that in turn creates a Board. Seems to work.
But in real life, multiple Games can be played with the same Board. What happens when we’ll start adding more features, like this one? We’re going to bend the model even further, and then we’re back at translation error land again. Welcome home, bug!
Plus, different models obscure understanding, but we’re sure we know what we’re doing. Which leads us to…
Ah, the “humble” assumption. What we think we know. And we assume that everyone else thinks the same. “No one will ever send a null”, right? No one will access this value at the same time as other, right?
We can’t really get away from those things. Otherwise we’re at square one – we’ll need to think about everything. And we won’t, because our brain tells us – everyone knows that. Everything we assume, we don’t write code for (the null thing), or if we assume the worse, too much code (syncing the value over threads). In the first case we’ll be surprised we were wrong, and in the second, we make the code so complex it’s hard to test and prove our assumptions were met. Then, we’re surprised we were wrong.
We make errors.
These are just few of my favorite bug origin stories. There are probably a few more.
We try to reduce the number of surprises by reviews and communications. And those work.
But bugs, like zombies, come back.
They always come back.
If you want less bugs, or at least extremely interesting ones, contact me!