This post originated from an RSS feed registered with Java Buzz
by Daniel Bonniot.
Original Post: Let the compiler help you, Laird!
Feed Title: Daniel Bonniot's Weblog
Feed URL: http://www.jroller.com/dbr/feed/entries/rss?cat=%2FNice
Feed Description: Design ideas around the Nice programming language
I've been looking around at Java-related blogs, and found this interesting experiment by Laird Nelson. Basically, it seems Laid is unnerved by the possibility that basically every line of Java code is a possible source of NullPointerException. He then went into the practice of strengthening his code to make it robust in case any reference actually holds null and not an object instance.
My take on this is that the motivation is sound. Programs should not fail at runtime. Since we humans are faillible, there should be as much support from programming tools to catch our errors. Of course, that's never going to be 100%, but the closer you get, the more energy we have left to think about the remaining problems, and the real hard questions pertaining to the task we are trying to perform.
So how do we get tools to prevent these NullPointerExceptions? It's about not using a value (null) in a context where it is not valid. Doesn't that sound like the good old example: do not add apples and oranges; do not try to multiply two strings? Yes, that's right: static type-checking! Now, it happens that most languages that include a null value (be it called NULL, nil, ...) make that value "magically" be a member of every type on earth. Which obviously lead to problems, since null is not a File, nor a String, nor anything else. We are building on a lie, and when that lie is found out (they always are, as our mums taught us!), that gives a painful situation...
I hear someone ask: "if null is not a member of any type, then how could we ever us it?" The point is that often attributes are optional. For instance, most people have a known father, but some don't. So when declaring a class to hold information about a person, you should declare that it has a field father whose type is "either a person, or null". I'll write that type ?Person, where the question mark indicates the possibility of the value being null. The great thing about using this type is that the compiler knows that this field might be null, so it can make sure that whenever it is used, that case is taken into consideration. Without this feature, you would at best signal in a comment to be careful that the value might be null. And very likely, someday, someone would overlook that comment, and forget the null case. And the really dangerous part is that since this case is rare, the program might seem to run fine, it might pass its tests, but eventually it will crash, and then this will mean debugging, maybe service outage, ...
So, by introducing the distinction between normal types, which do not allow null values, and optional types, prefixed by the question mark, for those cases where the null value is valid, you achieve several benefits. First, you give a standardized way to document where the null value is valid and where it is not. Second, you allow the compiler to make sure the null case is taken into account, which guarantees that NullPointerException will not be thrown at runtime. Thrid, it enables you not to need to program defensively against null values, since the static typing can guarantee you that a value is not null unless it is explicitely allowed.
This handling of null values is one of the features that Nice adds to Java. It fits into the general philosophy behind Nice, which is that it's possible to have a Java-like language with more static safety and more expressivity than Java. Just let the compiler take care of such details, and focus on your task!