When pressed, I bet you can think of an interesting dichotomy in the software world. On the one hand, we programmers seem an extraordinarily helpful bunch. You can generally picture us going to user groups, conferences, and hackathons to help one another. We blog, record videos, and help people out on Twitter.
But then, we also seem to tear each other apart. Have you ever hesitated before posting something on Stack Overflow? Have you worried that you’ll miss some arcane piece of protocol or else that you’ve asked a stupid question. Or, spreading our field of vision a little wider, have you ever seen nasty comment sections and ferocious arguments?
We programmers love to help each other… and we also like to rip each other to shreds. What gives?
Reconciling the Paradoxical
Of course, I need to start by pointing out that “the programming world” consists of many, many human beings. These people have personalities and motivations as diverse as humanity in general. So naturally, contradictory behavioral tendencies in the population group can exist.
But let’s set that aside for a moment. Instead, let’s try to squish the programming community into a single (if way over-generalized) human being. How can this person be so helpful, but also so… rude?
The answer lies in understanding the protocol of helping. The person presenting the help is an expert. Experts enjoy explaining, teaching, offering opinions, and generally helping. But you’d also better listen up the first time, pay attention to the rules, and not waste their time. Or they’ll let you hear about it.
In the programming community, we gravitate toward conceptual, meritocratic ladder ranking. Expert thus becomes hard-won, carefully guarded status in the community. Show any sign of weakness, and you might worry that you’ll fall down a few rungs on the ladder.
But We Still Make Mistakes
And yet, however expert, we still make mistakes. Of course, nobody would deny that. Go up to literally anyone in the field, ask, “do you ever make mistakes,” and you’ll hear “of course” or at least a tepid, “every now and then.” But a difference exists between making mistakes in the hypothetical and making a specific mistake in the moment.
As a result, many in the field try to exude an air of infallibility. Most commonly, this manifests in the form of that guy that never, ever says “I don’t know.” More generally, you can recognize it in the form of constant weighing in and holding forth on all sorts of topics. In this field, we do tend to build up an impressive beachhead of knowledge — algorithm runtimes, design patterns, API calls, tips and tricks, etc. Armed with that, we can take up residence in the expert’s chair.
But no matter how we try to disguise it, we inevitably make mistakes. Perhaps we do something as simple as introducing a bug. Or maybe we make a fundamentally bad call about some piece of architecture, costing lots of time and effort. Big or small, though, it happens. The interesting question is why? If we log Malcom Gladwell’s famous 10,000 hours of practice, and have heavy incentives to show no weakness, why do we still make mistakes?
Lapses in Concentration
Perhaps most simple and obvious, lapses in concentration will lead to mistakes. This applies no matter who you are, how much you practice, or what you know. This can happen in immediately obvious ways. For instance, your mind might wander while doing relatively repetitive programming tasks, like updating giant reams of XML configuration or something. Generally speaking, monotonous work creates breeding ground for mistakes (which speaks to why doing such work is a smell for programmers).
But it goes beyond the most obvious as well. Feeling tired or distracted can lead to concentration lapse mistakes. Interruptions and attempts to multi-task do the same. I don’t care how much of a programming black belt you may be — trying to write code while half paying attention on a status call will lead to mistakes.
Imperfect or “Noisy” Information
Moving beyond simple mistakes, let’s look at a category that tends to lead to deeper errors. I’m talking here about mistakes arising from flawed information. To understand, consider an example near and dear to any programmer’s heart: bad or incomplete requirements. If you take action based on erroneous information, mistakes happen. Now you might argue, “that isn’t my mistake,” but I consider that hair splitting. Other factors may contribute, but you still own that implementation if you created it.
But look beyond just bad information. “Noisy” information creates problems as well. If your business partners bury requirements or requests in the middle of lots of irrelevancies, this can distract as well. For all of their best intentions, I see a lot of this happening in expansive requirements documents that try to cover every imaginable behavior of a not-yet-written system right up front. You become lost in a sea of noise and you make mistakes.
These mistakes may come in simple forms, like missing buttons or incorrect behaviors. But they can also prove fundamental. If you learn at a later date that the system will actually only ever need one data store, you may have built a completely unnecessary data access layer abstraction.
Overconfidence or Not Enlisting Help
We’ve examined some causes that fall under “probably not your fault.” Now let’s look at one that falls under, “probably your fault.” I’m talking about unwarranted faith in your own decision-making.
As I mentioned earlier, in the giant ladder ranking of programmer meritocracy, “I don’t know” can knock you down a few rungs. (I’ll leave it to the reader to evaluate whether this happens in actuality or only in our minds.) This leads to a behavior wherein we may try to “wing it,” even in unfamiliar territory.
When we do this, we have no one but ourselves to blame for the inevitable mistakes. On my own blog, DaedTech, I once gave a label to those who frequently posture and fail this way: expert beginners. Of course, that label talks about someone of marginal competence, but even a bonafide expert can fall victim to too much self-assurance. The field of programming presents such immense and complex surface area that you will always have blind-spots. Pretending you don’t leads to mistakes.
Let’s get a little more philosophical here. I just mentioned that programming has too much ground for any one person to cover. This forces a choice between admitting you need outside expertise and making mistakes. But let’s expand on that even a little more.
Programming is knowledge work. This means that we, as programmers, solve problems rather than perform any sort of repetitive labor. Sure, you might write a handful of custom web apps that prove similar in nature. But this is a far cry from the cookie-cutter nature of, say, assembly line work. Even writing somewhat similar apps, all of our work involves solving problems that no one has yet solved.
And when you’re blazing a new trail, you will inevitably make mistakes. It simply comes with the territory.
In Fact, You Should Make Mistakes
I’ll conclude by going even further than inevitability. You should make mistakes. In the first place, I think that a culture wherein we consider mistakes signs of weakness is counter-productive and asinine. Having prominent experts say, “gosh, I really don’t know” encourages us all to do the same and it generally promotes a more productive culture.
But the benefit runs deeper. I’ve heard it said that, if you’re not making mistakes, you’re probably not doing anything interesting. And I firmly believe in that. Pushing the envelope means making mistakes. But, even beyond that, whether we make mistakes or not is less important than developing robust recovery mechanisms. We should design software and systems not with an eye toward perfection, but with an eye toward minimizing the impact of mistakes. After all, software is so fluid that today’s correctly functioning system becomes tomorrow’s ‘mistake’ when the requirements change. So you might as well get good at recovering.
So, why do experts make mistakes? Because we all do, and because our mistakes drive us forward when we learn from them.