Fernando Rodriguez's blog

Code Long & Prosper

nil is not the billion dollar mistake

Wed 10 April 2019

The Null Object Design Pattern and the billion dollar mistake

Since Swift was launched, one of Objective-C's perceived features has come under heavy attack: nil. It has been accused on being the boogey-man that Tony Hoare called the billion dollar mistake.

Hoare's billion dollar mistake

At a conference in 2009, Tony Hoare said:

I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). 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.

Many considered this actually meant that having a type to represent the lack of a value was inherently wrong and unsafe, and should therefore be banned from all languages.

Hold your horses. That is NOT what Tony Hoare said, and the Null Object Design Pattern is actually a useful, safe and vital pattern in any language.

This is much easier to understand with an example, so let's try one.

The Null Object Design Pattern

Let's assume we are building a Markdown renderer. You will probably need a parser and then some subsystem to format the text. Some of the formatting possibilities are:

  • bold
  • italics
  • code
  • etc...

A Text Formatter Hierarchy

It might make sense to build a class hierarchy of text formatters. Each subclass is responsible for taking some raw text and outputting the formatted text (let's assume we only care for html, as adding other output formats doesn't change the the design, and can be solved in Objective-C by using double dispatch).

text formatters

This class hierarchy has a small issue: it cannot represent text that has more than one type of formatting!

Such as bold code.

This could be solved by adding another subclass, that implements the Composite Design Pattern

The composite design pattern represents a group of instances that is treated as a single instance.

In our specific example, the CompositeFormatter can represent a set of other instances, such as a BoldFormatter and a CodeFormatter. By joining and applying both, we get the desired effect of bold code.

Composite Formatter

One problem left: edge cases!

There's still one feature in our domain that the class hierarchy doesn't handle well: a common edge case.

Most of the text has no formatting!

Even though the most common case is for text to have no formatting, our class hierarchy seems to assume that this never happens.

The common solution is to fill all your code with if statements checking if the text has to be formatted and if yes, pass it to a formatter.

Something along these lines:

-(NSString *)formatText:(Text*)aText{
    // Will assume that TextFormatter is a class cluster (https://apple.co/2IwWjj4)
    // that can infer which specific subclass should handle the formatting
    if [text shouldBeFormatted]{
        return [TextFormatter format:aText];
    }else{
        return aText;
    }
}

This is idiotic. We are needlessly filling our code with if statements that hide the domain logic and increase the cyclomatic complexity.

By the way, does the code above seem familiar? If you've ever programmed in Java, you've seen this pattern:

if( myVar != null){
    // do something
}

If both pieces of code seem similar, that's because it's the same bad solution to a common problem: checking, over and over, for a common edge case.

As software developers, we should always strive for the simplest solution that does the job. One of the best ways to remove complexity is to remove edge cases.

In OOP, the best tool to remove edge cases is polymorphism

In the example of the TextFormatter the easiest way to get rid of the common case of text not having format, is to create a NullFormatter.

This NullFormatter does something vital: Nothing. Whenever it receives a piece of text, it returns it untouched.

Thanks to the NullFormatter, now there are no exceptions: every text object has a TextFormatter. The common case where the text has no formatting is represented by the NullFormatter.

Now the class hierarchy correctly represents the domain and there's a single rule with no exceptions: every text has a formatter.

Null Formatter

The resulting code is far simpler, and the gazillion if statements scattered through our code have been swapped for a single polymorphic method format: within our class hierarchy.

-(NSString *)formatText:(Text*)aText{  
    return [TextFormatter format:aText];
}

Using the Null Object Design Pattern we reduced the complexity of our code by applying the DRY principle.

The usefulness of the Null Object Design Pattern

  1. The Null Object Design Pattern removes exceptions from the general rules implemented in our code.
  2. It has to be implemented for each class hierarchy.
  3. Within that class hierarchy, it plays the same role as the null element in Algebra (such as zero for real numbers and multiplication)

The Null Object Design Pattern plays the same role and is as vital as 0 is in addition.

Algebra Text Formatting
Elements Real Numbers Instances of Text
Operation Addition format:
Null Element 0 NullFormatter

nil in Objective-C

The catch in this pattern is the same in many other design patterns: it forces the programmer to do repetitive grunt work and creates boilerplate code.

The way Objective-C solves this, is by providing nil: a universal null object that works for any class. It will provide the do nothing functionality by ignoring all messages that are sent to it.

Objective-C is by no means unique here: other languages have taken the same route, such as Smalltalk, Snobol4 and to a lesser extent, Python and Common Lisp.

Recently, many languages influenced by ML (such as Swift, F#, Kotlin, Haskell, etc..) have taken a different route: a parametric (generic) type called Optional or option.

It is however, the same solution to the same problem: provide a way to represent a null element that does nothing, playing the same role 0 plays in Algebra.

So what was the billion dollar mistake?

If the Null Object is not only not a mistake, but one of the greatest ideas ever, what is the billion dollar mistake?

The billion dollar mistake was the way the Null Object was implemented in some languages, notably C.

In C, the Null Object was implemented as a pointer with an invalid address (0 or NULL). It was done so because that implementation perfectly matches the C Philosophy:

  • Simple
  • Fast
  • The compiler trusts the developer

In Objective-C, we had to inherit this decision, because Objective-C was designed to be a strict superset of C.

We are, however, far more shielded by the runtime and Cocoa from null pointer exceptions. With a modicum amount of care, your code should never crash because of that.

2 - Let expressions in F#

Thu 04 April 2019

Part of the F# Functions 101 series

the importance of a name

Like the pine trees lining the winding road

I got a name, I got a name

Like the singing bird and the croaking toad

I got a name, I got a name

I Got a Name

let the fun begin

When learning F#, there are two things you should grasp as quickly as possible: the let keyword, and functions. Both are essential for grokking the language.

let is by far the most important keyword you will learn. It's syntax is deceptively simple, and it has 2 main roles in F#:

Number 1: let creates bindings

A binding gives a name to a value (if you come from an OOP language, then whenever I type value, feel free to read object).

Some examples of values are:

42 // an integer
"functional programming is fun" // a string
[1;3;34;-58]  // a list of ints

Using let to create bindings is as follows:

let answer = 42
let motto = "functional programming is fun"
let entries = [1;3;34;-58]

The body of the let expression (the right hand side), can be much longer and have several lines. This is where the second role comes in:

Number 2: let creates scopes

Scopes are sections of your code where certain bindings (names) are valid.

Here's an example:

let z = 
    let a = 4
    let b = 5
    a + b   // This will be the value of z!

The scope is delimited by indentation, just like Python! Within the scope created by let z, a and b are valid identifiers and have a value respectively.

How long can the let expression be?

The compiler will keep evaluating the let body as far as possible (think of a greedy algorithm if you wish). It will stop when the indentation is reduced and will succeed if the last expression returns a value (for example, a + b in the example above). The value of the last expression will be the value of the binding.

If the last expression, does not eval to a value, the compiler will yell at you.

At this point, I would recommend playing around with the interactive FSharp and try creating different let bodies.

Functions are values too!

In the next post, we will learn about the most powerful feature in F# : function abstraction.

In a nutshell, functions are just another type of value within the language and can be treated just like any other value: ints, strings, etc...

Don't let the simplicity of this statement fool you! Within it, lies all the power and flexibility of F#.

You are now staring at an ordinary burrow in the middle of a field. Little do you know that this is the rabit hole, the one that will you take far down, straight into Wonderland!

Would you like to know more?

This post is part of a series on F# Functions 101.

  1. F# Functions 101 index
  2. Let the fun begin: let expressions in F#

1 - Everything no one told you about F# functions

Thu 04 April 2019

Part of the F# Functions 101 series

F# functions 101

First steps

This post is part of a series on F# Functions 101. This should give you a solid understanding of some of the most important concepts a beginner needs to grasp when learning F#:

  • let
  • functions
  • function evaluation
  • pure functions vs fake functions
  • the amazing power of partial evaluation or currying
  • and more!

Would you like to know more?

This post is part of a series on F# Functions 101.

  1. F# Functions 101 index
  2. Let the fun begin: let expressions in F#

Beginning F#

Thu 04 April 2019

First steps Let's learn F#!

Part of the F# Functions 101 series

F# is an incredibly easy language to pick up!

Not really, even though it should.

There are several hurdles on the way of the beginner. First of all, a really good book aimed at beginners. This is vital in a language plagued by TIMTOWTDIs.

F# is a functional language built on top of .NET, a strongly Object Oriented framework. This causes a lot of impedance between the language and the libraries.

It's like a Jedi and a Sith being siamese twins!

F# is not alone here. The same situation arises with Swift and Cocoa, although I feel like it's been better handled in the F# / .Net case.

One of the annoyances of having an evil siamese twin, is the curse of the TIMTOWTDI: Having a gazillion ways of doing the same thing, without a guide to which one is best, at least for newcomers, is very confusing.

There are some books...

Expert F# is horribly disorganized, keeps jumping around concepts and has the obnoxious habit of mentioned things that were not explained earlier.

It might be a great reference, but it's certainly not good learning material.

The F# book is also very frustrating. A lengthy dissertation of all the TIMTOADIs without much guidance at all: you order a steak and the waiter instead goes on to explain all the different cuts in a cow. Dude, I just want a steak!!!

F# Applied is pretty good, but not aimed at beginners.

DDD made functional by Scott Wlaschin is awesome: provides guidance and promotes great design, but again, it's not for beginners...

Put my blog where my mouth is

I'll try to alleviate this entry barrier by posting my notes as I learn the language. Join me and let's learn an awesome language tha can be used for backends, Data Science, web frontends and even mobile apps! How cool is that?

First things first

We will start by the most basic building block: functions.

Other posts in this series

  1. F# Functions 101 index
  2. Let the fun begin: let expressions in F#