Poor Programmers Out-Breed Good Ones

Today, aside from AI and a few other areas, most commercial code involves far more people and effort than is actually needed. We desperately need to take stock of where we are.

Poor Programmers Out-Breed Good Ones
“The fault, dear Brutus, is not in our stars / But in ourselves, that we are underlings.” (Julius Caesar, Act I, Scene III, L. 140-141).

I've spent decades in search of excellence in software. I've learned dozens of languages and technologies and helped hundreds of team struggle with "How can this be so difficult for us yet (seemingly) so easy for others?"

Join the fun!

Writing my second book, I came across a completely unexpected answer: the power of mediocrity Because programming is logical and boolean, we view the work itself as logical and boolean, but it's not that way at all.

Let me state this thesis in the strongest form possible in order to help you, the reader, criticize it better: the vast majority of commercial programming feature requests involve well-trodden, easily-accomplished programming that can either be easily maintained or easily replaced. Poor programmers are not incapable of delivering such features, at least initially, but they are unwilling or incapable of delivering them in a direct and simple manner. When they fail it is not because of a failure of some immediate test, it is because when stumped and unable to deliver directly, they continue to add more and more unneeded complexity, either to the language, the architecture, the programming process, the documentation, or so on.

In my writing the conclusion I reached was this: Good Enough Programming is programming that delivers value that you can walk away from and never re-open. That's it. It's not perfect, "right", hell it might not even look like anything. If you never re-open it, none of that matters. We're adding a bunch of stuff to our programming practices that's unneeded, and as we add each thing it only breeds more things that need to be added. It's cumulative.

Another way of putting it: poor organizations, when they are faced with a problem, assign a person to it. The problem seemingly goes away but in reality just multiples and becomes many more smaller and less visible problems. This process repeats itself.

We are all poor programmers in our own way. So this advice is not along the lines of "just get smart or do X and you'll stop doing stupid things". I wish it were so simple. It is not. This divide-and-conquer mentality works extremely well in the real world using physical objects and it's not something we ever want to give up. It just doesn't work in programming-related activities.

Poor programmers multiply without end.

This has several surprising implications.

If you're being hired as a programmer by another programmer, odds are that it is because of a failure of the other programmer to simply deliver the value requested by the user. This is due to an honest yet misguided framing of the problem by that programmer or organization.

Once you're hired, you've bought into this misframing. At this point, you're either tasked with telling your boss and the organization that it's mistaken or continuing to create more unnecessary complexity by carrying on in this mistaken direction. It is unlikely that you'll be successful changing the minds of just one person, much less an entire organization. The more people involved, the less likely it is.

If you are hired to deliver a feature with value and deliver it in a simple way that you can walk away from, you're gone. Good programming is self-limiting by nature. Nobody keeps around the guy who invented the record player in order to play more records at home.

You shouldn't see good programmers in larger corporate settings. The concepts don't mix. The longer good programmers stay in large settings, the more they train themselves to be poor programmers.

Once again, this is simply the natural result of applying our wonderful ability to break up problems into smaller, more manageable pieces in a place where it doesn't work that way. No malice, ignorance, or pig-headedness is required. In most cases this is a feature. Just not here.

In fact, we enjoy all of this! Who doesn't like setting up a logical puzzle around a technical problem, then coming up with a solution that wasn't evident before? I'd argue that this is constitues the entire fun of coding.

These are fun, belief-challenging conclusions. This is why I love them so much. I know there are edge cases, but the general truth seems to me to be too important to ignore. For example, it follows that the more you spend actually programming in most commercial environments, the more poor of a programmer you are! We talk about lazy programmers being good ones, but it's another thing entirely to generalize to the point that in most every case lots of activity is counterindicative of good programming.

Since everybody knows complexity is a problem but nobody seems to be able to offer practical advice on dealing with it, this cognitive conflict is too much for most folks to bear. Therefore we continue to redefine what good programming is, doing what we do best: adding more and more detail and complexity to the definition and setting up trainings and certifications and such.

This is important to know because AI will not fix our misconceptions about what our jobs are. It'll only help us do more of what we're already doing.

We have all of these frameworks, systems, rules, and structure in place. Accept these or move on. Instrinsic failure is never visible. Fish don't see water.

I am not pessimistic. I've worked through my own answers and strategies here and I don't think there's anything fuzzy or mysterious at all about how to solve this problem. It's just counter-intuitive and we don't want to do it. I get it. Yet still here we are.