Saturday, July 22, 2017

Down with NULL!

Many consider the introduction of null as the worst mistake of computer science.

Usage of null makes for sloppy code, including cascading and often redundant null checks. It makes for buggy code due to missed null checks, and it makes for poor APIs.

It’s Tony Hoare’s billion-dollar mistake.

“I call it my billion-dollar mistake…At that time, I was designing the first comprehensive type system for references in an object-oriented language. My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn’t resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years.”.

– Tony Hoare, inventor of ALGOL W.

Unfortunately, he wasn’t the only one that couldn’t resist the temptation to put in a null reference. The inventors of Java, C# and many more fell into the same trap, causing twenty more years of pain and misery.

Seems like we had enough, as the designers of newer languages like Rust and Swift realized that that only way to eliminate the destructive side effects of null is by avoiding it altogether.

These languages use the optional feature instead of null.

The beauty of the optional feature is that only optional properties or methods can be null. If you try to set a non-optional property to null, you'll get compilation error.

That's an excellent language feature, because it allows to reliably exclude the possibility of null everywhere in the code, except for the parts that use optional, which should be the exception rather than the rule.

Languages like c++ and Java have added optional support via a community library, or directly to the standard library. It helps, it’s better than nothing, but it’s really too little too late.

Starting from Java SE 8 you can do this:

class Box
{
   Optional<Integer> color;
}
Box box = new Box();
box.color.ifPresent(x -> System.out.println(x));

Unfortunately, since Java’s type system allows null everywhere (If you try to set a non-optional property to null, the compiler wouldn’t mind), we can’t reliably exclude the possibility of null, and we still end up with null checks everywhere.

Recognize this?

if (str != null && !str.equals("")) {
// Do something with str
}

In order to effectively combat the the terror of null, the optional feature must be backed into the language from the very beginning, and it must be enforced wholesale by the compiler.

Swift is a great example for such language. Instead of allowing every property (or method) to return nil, Swift forces you to explicitly declare that a property can be nil, otherwise, it assumes that the property is initialized.

So the below code will not compile, since the property ‘color’ is not initialized!

class Box {
     var color: String
}

You must do something like this:

class Box {
   var color: String = "Red"
}

Now, even if you never saw the implementation of Box, you know that you can safely use the property color without nil check..

// Create instance of class.
var example = Box()
if (example.color != nil) ... // NO NEED!

You can explicitly declare that a property or a method can be nil, by making it optional (adding ‘?’ post-fix after the type). However, especially for properties, that should be the exception rather than the rule.

class Box{
   var color: String = "Read"
   var colorOptional: String?
}

Now the caller knows that nil check is required. The caller doesn’t have direct access to the property, it has to unwrap it first using ‘!’ (see line 20)

// Create Box instance.
var box = Box()

if (box.colorOptional == nil){
   print("It is nil")
}

// Instead of nil check, we can do this:
if let c = box.colorOptional {
   print("you shouldn't be here!")

}

// Assign optional to String value.

box.colorOptional = "Blue"

if let c = box.colorOptional {
   print("Box has color \(c)")
   // The optional can be accessed with an exclamation mark.
   print(box.colorOptional!)
}

Now that’s how you fight against the terror of NULL!