Imagine There’s No Null

Wednesday, May 27th, 2009

A couple of weeks ago I spent a considerable amount of time chasing down bugs involving null in a large code base: null checks after a variable had already been dereferenced, nulls passed to methods that would immediately dereference them, equals() methods that didn’t check for null, and more. Using FindBugs, I identified literally hundreds of bugs involving null handling; and that got me thinking: Could we just eliminate null completely? Should we?

What follows is a thought experiment, not a serious proposal. Still it might be informative to think about it; and perhaps it will catch the eye of the designer of the next great language.
(more…)

In Praise of Draconian Error Handling, Part 1

Monday, January 12th, 2009

I’m doing a bit of work on XOM, trying to optimize and improve some of the Unicode normalization code. A lot of this is autogenerated from the Unicode data files, and I’m actually working on the meta-code that parses those files and then generates the actual shipping code. In this code, I’m setting up a switch statement like this one:

       switch(i) {
          case 0:
            return result + "NOT_REORDERED";
          case 1:
            return result + "OVERLAY";
          case 7:
            return result + "NUKTA";
          case 8:
            return result + "KANA_VOICING";
          case 9:
            return result + "VIRAMA";
          case 202:
            return result + "ATTACHED_BELOW";
          case 216:
            return result + "ATTACHED_ABOVE_RIGHT";
          case 218:
            return result + "BELOW_LEFT";
          case 220:
            return result + "BELOW";
          case 222:
            return result + "BELOW_RIGHT";
          case 224:
            return result + "LEFT";
          case 226:
            return result + "RIGHT";
          case 228:
            return result + "ABOVE_LEFT";
          case 230:
            return result + "ABOVE";
          case 232:
            return result + "ABOVE_RIGHT";
          case 233:
            return result + "DOUBLE_BELOW";
          case 234:
            return result + "DOUBLE_ABOVE";
          case 240:
            return result + "IOTA_SUBSCRIPT";
          default:
            return result + "NOT_REORDERED";
        }

And then I stop myself. Do you see the bug? Actually it’s a meta bug that leads to the true bug.
(more…)

Prefer Multiline if

Thursday, January 1st, 2009

C-family languages including Java, C#, and C++ do not require braces around single line blocks. For example, this is a legal loop:

for (int i=0; i < args.length; i++) process(args[i]);

So’s this:

for (int i=0; i < args.length; i++) 
    process(args[i]);

However both of these are very bad form, and lead to buggy code. All blocks in C-like languages should be explicitly delimited by braces across multiple lines in all cases. Here’s why:
(more…)

Java is Dead! Long Live Python!

Tuesday, December 9th, 2008

Version 3.0 of Python has been released. Notably Python has again done something Java has long resisted: it has broken backwards compatibility with Python 2.x. Notable fixes include a much saner string processing model based on Unicode. I am told by my Pythonista colleagues that a lot of other weirdnesses such as the print operator and the meaning of parentheses in except clauses have been cleaned up as well. Though I don’t expect all Python programmers to upgrade immediately (and version 2.x will be maintained for some years to come) version 3.0 is clearly a simpler, better, saner language than version 2.x that will enhance productivity and make programmers’ jobs more fun. Bravo for Python. This is clearly a living, evolving language.

Java by contrast, is dead. It has at least as much brain damage and misdesign as Python 2.x did, probably more; yet Sun has resisted tooth and nail all efforts to fix the known problems. Instead they keep applying ever more lipstick to this pig without ever cleaning off all the filth and mud it’s been rolling in for the last 12 years. They keep applying more perfume when what it really needs is a bath.
(more…)

Keep Your Methods Private and your APIs Minimal

Tuesday, November 11th, 2008

I was reminded once more today just how important it is to write minimal APIs that don’t expose more than they have to. Briefly I had code like this:

 private boolean flag;

 public boolean getFlag() {
   return this.flag;
 }

  public boolean setFlag(boolean value);
    this.flag = value;
  }

Pretty boilerplate stuff, I think you’ll agree.

However I noticed that after some refactoring that merged a couple of classes I was now only calling getFoo() from within the same class (or at least I thought I was) so I marked it private. Eclipse promptly warned me that the method was unused so I deleted it. Then Eclipse warned me the field was unread. That seemed wrong so I looked closer and yep, it was a bug. The feature the flag was supposed to control was always on. During the refactoring I had failed to move the use of the flag field into the new class. I added a test to catch this, and fixed the problem.

What’s interesting about this example is that I found the bug only because I was aggressively minimizing the non-private parts of my API. The less public API a class has, the fewer places there are for bugs to hide. The less public API there is, the easier it is for analyzers–static, dynamic, and human–to detect problems.
(more…)