Tuesday, November 25, 2008

I don't trust software. I don't trust what other people write and I don't trust what I write. That's because programmers make mistakes all the time, and there is no sure method of finding all of them. The more code there is, the more bugs there will be.

There are a number of things that can mitigate this such as coverage testing and code reviews, but my favorite is robust compilers, and right now my favorite compiler is Java. This is mostly because I'm used to it. I'm so used to it that I actually dream in Java.

Java does a lot to help prevent programmer mistakes, or to at least point mistakes out to the programmer. Recently I've been working on a C# project and in desperation I've resorted to a number of "C# for Java Programmers" documents on the web. One good one that I read yesterday had a section on exception handling that explained how C# doesn't provide any compile-time exception handling. I.E. there's no "throws" clause. This is a huge deficiency in C#'s ability to help the programmer catch mistakes. Basically you have to rely on documentation to have any clue how a method you are calling might fail. I don't know about you but I trust documentation even less than I do code.

In fact, one of my gripes with Java is that it allows some classes of exceptions to pass through without requiring a throws clause. These include array index out of bounds, integer parsing errors, and the dreaded null pointer exception.

Null pointer handling is the hardest aspect of Java programming for me. I keep wanting the compiler to help me with it but it just refuses. I end up having to remember to always check and that results in code bloat. There seems to be an unavoidable tradeoff between the risk of null pointer exceptions at runtime and code bloat. But this doesn't have to be. The compiler could be of enormous help here.

First of all, the compiler knows exactly where pointers are referenced. It also knows, at each of those places, whether the pointer could be null or not. For example,


Integer a = new Integer(0);
System.out.println(a.intValue());


a null pointer exception is not possible at line 2, whereas in


void someMethod(Integer a) {
System.out.println(a.intValue());
}


a null pointer exception IS possible at line 2. Now if we had a parameter modifier "notnull", then


void someMethod(notnull Integer a) {
System.out.println(a.intValue());
}


a null pointer exception would not be possible at line 2. The compiler would then generate an error any time someMethod was called in a context where its argument could be null. I think that null pointer problems would almost disappear if the compiler supported this, and my trust in code I and other programmers write would go up a couple of notches.

I've searched for tools that can do this sort of thing with annotations but haven't found anything that really works. I've found I can turn on a warning in eclipse that supposedly will detect possible null pointer problems but it only catches a few of them. At the moment, writing my own tool is a bit beyond my reach, so I'm waiting, continuing to search for a solution occasionally, and continuing to mistrust my own code.

No comments: