Someone emails me asking why a bioinformatics program (more specifically a short-read aligner) that works for someone else gives them a segmentation fault when they try to run it using the same command-line arguments. The program is written in C and is being run on a computer running GNU/Linux. This problem has caused him quite a bit of consternation and it is only after a while he emails me wondering why. After looking at the problem a bit and eliminating some usual suspects, it turns out that one of the files that the program was trying to read had restrictive permissions that did not allow the user to read it. Why does this cause a segmentation fault? Simply put, poor programming. All that needed to be done was to make sure the FILE* pointer actually pointed to something before using it. In other words, checking the return value of a function that has a somewhat high probability of failing. You see this all the time in software development (and use), simple things that can be done to make the program more reliable that just aren't done. It is especially prevalent in biological software.
So why are these little things not being done? Are they not being taught? Are they not being learned? Are programming languages to blame? I think it is a little bit of all these things. Checking the return value of a function you call is mentioned when you begin learning to program or learn a new language, but from the very first example you are shown to the last, error checking is left out to save space, improve readability, increase clarity, or some other such excuse. Let's face it, most "Hello, world." programs you see do not look like this (and even it does not check the return value of
printf (not saying that you should)). Scripting languages also tend to encourage the daisy-chaining of commands. This nesting if commands not only discourages checking return values, it more or less prevents it. Ruby, while a great language, seems to suffer from this quite acutely because of the ease of sending one message after another to objects (even using pipes). Of course, Ruby, like most OOP languages, has exceptions, but it seems they are rarely seen out in the wild.
So how about this for a New Year's resolution: check the return value of functions/methods you call. You can start small: just check the return value of your
system() calls. Then maybe you could gradually checking more and more return values. After you get used to that, you can added useful error messages to the user when things do go bad. Finally, you could have your functions/methods return useful values themselves. Think of the possibilities.