Common programming errors and how to avoid them

Tags:

Back in august, I introduced the error tracking challenge. While it didn’t get as much participation as I had hoped for, I did manage to collect some results.

In this post, I’ll go through the most common ones, and suggest some approaches to avoiding them. Suggest your own errors and tips in the comments!

Boolean logic errors

This was the most commonly encountered problem. I have also made mistakes with boolean logic more than enough times.

Boolean logic errors usually manifest in if-else statements, as they are the main pieces of code where you may run into complex statements to determine what to execute.

There are various ways to avoid these, ranging from utilizing OOP better to splitting up conditions to multiple statements:

  • Split conditionals into multiple statements: As this tip’s name says, split your complex conditionals over multiple statements. Not only will they be more readable, they can convey the meaning much better.
    if(!($user->level == 1 && in_array($bannedUsers, $user->id) || 
      $page->name == 'index') {
      ...
    }
     
    //vs
     
    $isMainPage = $page->name == 'index';
    $notBanned = !in_array($bannedUsers, $user->id);
    $loggedIn = $user->level == 1;
    if(($loggedIn && $notBanned) || $isMainPage) {
      ...
    }

    I had a better example in mind from some recent code I modified, but I forgot it. However, this kind of made-up looking example still demonstrates the point – as you can see, the condition is much cleaner and it’s quite obvious what the requirements for the if-clause passing are.

    In fact, while writing the above example, I almost made a logic mistake.

  • Utilize OOP and polymorphism better: Often an if-else may be used to determine some course of action. In many cases, this could simply be abstracted into a class, and the concrete implementation of it would determine the course of action, without the calling code needing to use if-elses.

    There’s a great Google Tech Talk about Inheritance and polymorphism which shares a great deal of information on how to avoid conditionals completely.

Typos or unintentional omissions

Typos and omissions are some of the most common issues people told me about. Typos should be quite obvious: Misspelled variable names, function names and such. Unintentional omissions may be a little less clear at first – By omissions, I mean things like forgetting to remove debug statements, forgetting to upload a file or other things like that.

I’ve grouped these two mistakes under the same headline, as they belong in the same category: Mistakes caused by not paying enough attention, or in other words, being sloppy. Another cause is plain and simple forgetfulness.

While these two aren’t always very fatal mistakes, they can be problematic and annoying. For example if you check in code with typos or omissions to source-control and your coworkers get broken code.

How to avoid typos?

  • Use a programmer’s editor or an IDE. They will often support code-completion and are often able to highlight misspelled names
  • Write slower: While this sounds really obvious, you might not really need to type that fast. While I personally take some pride in being a fast typist, sometimes it’s just difficult to write things correctly when you’re simultaneously thinking about things like implementation details or how to name your variables etc.
  • Become a better typist: The opposite to the above, by becoming a better typist you can write faster and make less mistakes. While learning to be a fast writer may not rank very high on your to-do list, there are ways to make it quite fun. A good example is Typing of the dead
  • Get a better keyboard: Your keyboard may not be bad per-se, but perhaps you’d be more comfortable typing with a different one? I’ve noticed some changes in my correctness after getting a Logitech Wave keyboard to replace my aging Microsoft Multimedia Keyboard

A reader also suggested learning to use the dvorak keyboard layout instead of qwerty. If you have the patience to suddenly become the world’s slowest typist for a while when learning the new layout, this may be a fun and useful skill.

A spelling corrector may also be a good thing to have at hand.

What about omissions?

  • Read through diffs: Before commiting code to source control or creating a build, you can save your and everyone else’s time by going through the diffs for your changes. Not only will this let you spot any accidental omissions, you may actually spot a genuine bug while at it. Even better, you might want to get someone else to review the code with you
  • In general, version control tools like svn and git are good for avoiding omission-like mistakes. They can display you a list of modified files, unversioned files and other such things, which can help you find the errors.

Debugging mistakes

While not strictly a programming mistake, these are very much related.

Debugging mistakes can be so many things that I’m not going to go into all specific details. However, there is one common occurence: Wrong debug methodology.

How do you know your debug methodology is wrong?

You constantly go deep into code to figure out some problem, and it turns out it was something really simple, such as a missing file.

The old IT support mantra comes to mind:

– Is it plugged in
– Is it powered on
(repeat for each peripheral)

While this appears in various tech support jokes and such, this is a valid methodology: By ruling out the mistakes that are easiest to detect, you can save a lot of time if it was one of them.

Quite recently, I worked on some code that needed to be built to run. I could debug it from the IDE without building, and for some reason the code worked perfectly well in the IDE but not with the build.

I probably spent an hour or more, looking into various internals of things that seemed to be causing the issue. In the end, it turned out the build script was broken: A new directory I had added wasn’t included in the build, breaking the application.

If I had checked the relatively easy to test issue of having all directories in the build, I could have saved much time.

If you have a bug that seems elusive, check the obvious things before spending a lot of time debugging it. It may end up saving you much time and nerves.

JavaScript closure misunderstandings

While the other problems aren’t language specific, this one was also common enough to include in the list.

JavaScript closures can be very confusing if you aren’t used to them. I used to get confused by them all the time.

The typical mistake looks like this:

var obj = {
  prop: 10,
 
  myFunc: function() {
    alert(this.prop);
  },
 
  otherFunc: function() {
    setTimeout(this.myFunc, 100);
  }
};
 
obj.otherFunc(); //does not alert 10 correctly!

While the problem here is obvious to JavaScript veterans, it’s not so easy for beginners – even if they’re experienced in programming otherwise!

The fix to above is to wrap the timeout call:

var self = this;
setTimeout(function() {
  self.myFunc();
}, 100);

I won’t go into more details here, but there’s plenty of material on JS closures on the web.

What did I miss?

Out of the dozen or so mails, these are the most common ones. I was hoping to list at least 10, but due to lack of participation I couldn’t.

Do you have a common problem you encounter when programming? Do share it, or your other tips , in the comments!