Code is for humans, computers don’t care

How to write bug free code part IV
Reading Time: 6 min

This is part IV in a series about how to write bug free code. If this is the first encounter, then I recommend to start with part I.

In part III I wrote about how to exterminate bugs:

Bugs thrive in hiding, under rocks and vegetation.
The first step is to remove as many hiding places as we can.
Then we gradually reduce the remaining spaces until there is nowhere to hide,
and when they crawl out we just KILL THEM ALL!

In that part I focused on the dependencies in software development. But bugs are hiding in many places. This part is about how they hide in our communication, more specifically our communication with our computers.

Developing software is all about communication

There are as many paths from idea to a finished product as there are projects. What they share is that there are humans all over the place. Depending on size and type of company there can be more or less layers but in all cases there is a tremendous amount of communication that need to happen.

A simplified path from idea to product could look something like this: inception, research, definition, specification, implementation, testing. Each step involves different roles and humans, each step will inevitably lead to misunderstandings, no matter how thorough we are. We are human after all!

Not only are we dealing with human to human communication. The code we write is supposed to tell the processor what to do. Since the processor isn’t a mind reader it will also misunderstand our intentions from time to time.

All these misunderstandings, human to human to machine, lead to bugs, i.e. code that generates “incorrect”, “unexpected”, “unintended” results on some level.

So in order to write bug free code we need to get better at communicating in all steps in the process. The human to human part will be covered in a future article, this will focus on how we communicate with our computers.

Let’s instruct a computer!

If you ask Wikipedia a computer program is defined as “a collection of instructions that performs a specific task when executed by a computer”. Sounds like fun! Then I found this wonderful quote from Donald E. Knuth:

“Let us change our traditional attitude to the construction of programs: Instead of imagining that our main task is to instruct a computer what to do, let us concentrate rather on explaining to human beings what we want a computer to do.”

The Don is named in a Quora reply as someone that might be capable of writing bug free code. The quote is about Literate Programming but I am about to use it for my own sinister purposes! I think the idea can be applied on any programming language, paradigm or task.

Who will read the code?

A processor doesn’t understand anything of the code we write, it requires it to be compiled into machine code, which in no way resembles what we put in.

So it is a little misleading to think that we write code for the computer.
We actually write the code for ourselves, to concretize what we want the computer to do. The code will only be read by the developers working on it and anyone who needs to improve the code in the future.

The computer doesn’t care.

Writing code for humans

So we are not writing the code for computers, we are writing it for humans. The code must of course do what it is supposed to do, but if humans doesn’t understand it, or it seems obscure, convoluted and ambiguous, then it doesn’t fill its purpose.

The obvious example is when someone eventually has to improve the code. If it doesn’t make sense then a complete rewrite could be faster than reverse engineering.

It could actually be the same developer that wrote the original code but 6 months later…

Removing some rocks and vegetation

Writing the code for humans is a big thing for maintainability, but it happens to be essential for writing bug free code too.

Bugs love the obscure, convoluted and ambiguous. Whenever we make the code easier to understand we remove the places where bugs can hide, they simply cannot survive in plain sight.

Below is a list of possible hiding places. It is a mix of high and low, and it is in no way complete. The purpose isn’t to write a checklist, it is to give examples of how we create places for bugs to hide by forgetting that we are writing code for humans. If you are not The Don I am sure you will find your own favorite hiding places 🙂.

Happy bug hunting!

…can you please stop saying that?

Encapsulation, decoupling, cohesion…

…are all covered in part III Escape Dependency Hell. The architecture is the foundation which enforces healthy restraints and consistency on the implementation of functionality.

Having a good separation of concerns doesn’t only affect code robustness, it is also making the code easier to understand. which means more dead bugs.

No one will ever see your work

…except for those who need to improve it (including yourself).

Being a developer is a highly creative role, but unlike other creative roles no one will ever see your work, they will only experience the result that your work produces.

Writing code is not a beauty contest and should not be done to impress, it is written to be understood, the beautiful result is almost a side effect 🙂.

Write Honest Code

Some concepts sound so perfect that we don’t even question them, we just want them to be true. That is why elegant code design is the perfect hideout for bugs. It is elegant because it seems flawless, but is it really?

It is not until something is stated explicitly that the flaws become apparent. So let it be verbose, explicit, concrete, let it be as ugly as it is.
The code doesn’t try to hide anything, it is Honest Code.

There is a beauty in that too.

Sometimes you should just Repeat Yourself!

DRY, Don’t Repeat Yourself, and Generalization are great principles but need to be applied with a lot of common sense. If it increases readability then of course, if not then we need to weight the pros and cons.

The fear of duplication of code is often overblown. Yes, repeating ourselves seem like a bad idea, and more code means more potential errors. But if the code is trivial and it helps readability, so what? Anything that makes the code harder to read will increase the probability of bugs, in many cases more than the duplication of code would do.

And even if we have a strong case to generalize, let’s do it when we know that the generalization covers all use cases. Remember, premature Generalization and DRYing is a form of premature optimization, the root of all evil (not really, please see YAGNI vs. YAKYNT).

Hiding complexity doesn’t make it go away

There are two reasons to hide complexity. Either you sweep it under the rug and pretend it doesn’t exist which obviously is a really bad idea. Or you encapsulate it so you actually reduce complexity where it matters. Just be aware which option you are going for.

Some languages doesn’t give you a choice. GC abstracts away the explicit handling of memory which is nice, but where to optimize if you need to? Asynchronous code can look misleadingly clean and simple, e.g. async/await, but do you really know what is happening behind the scenes?

If you do something “just to be sure”…

…then you actually don’t know what your code is doing. AND you are further obscuring the code by adding code with unclear function. Double trouble.

If you are not 100% sure what your code is doing, then go back and rethink.

Constantly clean up your mess!

Cutting corners is only a short term strategy. When you are done experimenting, make sure you clean up after you. Dead code is dead and should be buried immediately, otherwise it starts to smell. Functions that are not used or commented out should not distract us from the stuff that really matters, so please delete.

What exactly does that object named “data” contain?

I should not have to say this but…

Name things based on what they actually are, name properties based on what they actually contain and functions on what they actually do. Never mind if the names are long, mind if they are actually correct. And the moment we realize that they are not correct, refactor.

Sometimes I hear the argument that explicit names get too long and the code gets hard to read. What is hard to read depends on why you are reading it. If you are working with the code the naming could be whatever, if you are trying to understand the code, then “data” might not be that helpful.

Flexibility is not a feature, it is a curse

More is not better, never was and never will be. There is definitely no value in having 10 different ways of doing the same thing (JavaScript, I am looking at you). The architecture suggested in part III has as one purpose to reduce the number of options, which will lead to higher quality and consistent code.

One option is ideal, the best option. Personal taste doesn’t count 😜.

If you are going to write crappy code…

…please at least be consistent. Then we might figure it out eventually.

And if all else fails…

…write comments and documentation. I am not kidding. Comments and especially documentation is in most cases time consuming to write, never complete and never up to date. Spend the time on writing better code instead!

Ok, that was a slight exaggeration. I do have some ideas about specification, documentation and how it connects to an iterative work process, but that will be another article.

There is a lot more to say

This was more of a brain dump but I hope you get the idea.

We are not writing code to instruct a computer what to do, we are writing code for humans, for ourselves, to understand and concretize what we want the computer to do. Writing code that works is only half work done.

I will for sure come back to this and update based on additional thoughts and feedback.

RELATED ARTICLES

Do what I mean, not what I say!

Leadership through mind reading — a practical guide

Escape Dependency Hell!!

How to write bug free code Part III

It’s the principles, stupid!

How to write bug free code part II

Join the Dinahmoe Newsletter

Every sometimes we post about what we have been up to, about new projects, articles and products.

We will never flood your inbox, most likely the opposite (?). But it’ll be fun, we promise!

We use MailerLite as our marketing automation platform.By clicking below to submit this form, you acknowledge that
the information you provide will be transferred to MailerLite for processing in accordance with their Privacy Policy and Terms of Service.