What are some of worst
punishments for theft?

  • Mutilation of a hand
  • Exile
  • Hard Labor
  • Prison
  • Penalty Fee

Could we consider some of those for coders that use irresponsibly null?

Not a new idea...

A Million Ways to Die
(if you use null)

All SuperHeroes must die 
(when they use null)

Die Hard
(after using null)

Machete Kills
(using nulls)

Null Must Die

Seriosuly...

2016 should be

the year in which 
we stop using null
in our code!

What is null?

If you Google it,
you may find
that there are 9
meanings for null...

...that proves that
coders, above all, have misused null... a lot!

The real
definition of null?

The value for a
reference that doesn't
refer to an object

A way to say:
"this reference doesn't refer to anything"

It's a little confusing, I know!

int main() {
   int n;
   // possibly more code
   n = foo();
}

People used to
code like this!

int main() {
   int n = 0;
   // possibly more code
   n = foo();
}

Later someone thought a "better" way

What about
pointers / references?

What is a good "zero"
value for a reference?!

NULL

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. -- C.A.R Hoare

If people only use null
as a "zero" value for reference there
wouldn't be much
of a problem

Lisp

A programming language made on the idea of processing lists. How was them implemented?

A List is

  • A node, called head which holds
    a value and a reference...
  • ... to another list, called the tail
  • An empty list is called nil, and it
    is used to signal the end of the list

When someone thought of implementing that idea in OO...

public class LinkedList<T> {

  private class Node {
    private T value;
    private Node next = null;

    public Node(T value) {
      this.value = value;
    }
  }

  private Node head = null;
  private Node last = null;

  public void add(T value) {
    Node temp = last;
    Node node = new Node(value);
    last = node;
    if (head == null) {
      head = node;
    } else {
      temp.next = node;
    }
  }
}

That seems
harmless, right?

null is not the same as nil

  • nil is an empty list
  • null signals that a node
    doesn't have a neighbor, yet
  • One option for implementing nil
    is to use a null reference

What would be a more accurate implementation?

public class LinkedList<T> {
  private Node NIL = new Node();
  private class Node {
    private T value;
    private Node next = null;
    private boolean isEmpty;
    public Node(T value) {
      this.value = value;
      isEmpty = false;
      next = NIL;
    }
    public Node() {
      isEmpty = true;
    }
  }
  private Node head = NIL;
  private Node last = NIL;
  public void add(T value) {
    Node temp = last;
    Node node = new Node(value);
    last = node;
    if (head.isEmpty) {
      head = node;
    } else {
      temp.next = node;
    }
  }
}

Going back
to null, here's
when it 
becomes harmful...

V Map::get(Object key)

Returns the value to which the specified 
key is mapped, or null if this map 
contains no mapping for the key.

When you jump from

zero value to signal absence of value, you
have a huge problem!

There is nothing in the signature of a method
that says that a null
may be returned!

factory.getFoo().getProperty("bar").getString();

This looks harmless!

...what about nulls?

It's so easy to forget
null-checking!

And null checking code is way messier!

These approaches hide
the real problem!

If you were to
paint a portrait
you wouldn't use
a roller brush!
It's not the right tool!

Null should be used as...

an implementation detail

public class LinkedList<T> {
  private Node NIL = new Node();
  private class Node {
    private T value;
    private Node next = null; // I'm null but nobody will ever know :)
    private boolean isEmpty;
    public Node(T value) {
      this.value = value;
      isEmpty = false;
      next = NIL;
    }
    public Node() {
      isEmpty = true;
    }
  }
  private Node head = NIL;
  private Node last = NIL;
  public void add(T value) {
    Node temp = last;
    Node node = new Node(value);
    last = node;
    if (head.isEmpty) {
      head = node;
    } else {
      temp.next = node;
    }
  }
}

Never let null be
part of the API
of your code!

Are you a
believer now?

This could be the Programming Community when we all
agree to use null just as an implementation detail!

How do we write null-less code?

Step #1

Don't accept null arguments in methods

void doIt(Foo foo, Bar bar) {
   if (bar == null) {
      // do this
   } else {
      // something else
   }
}

Your code looks messier, it's probably breaking SRP and is more error prone

doIt(foo, null);

This looks weird

doIt(foo);

Much better

doItWithABar(foo, bar);
void doIt(Foo foo) {
  Bar bar = giveMeADefaultBar();
  doItWithABar(foo, bar);
}

If you will need a bar anyway

// code
Bar bar = service.getIt();
doIt(foo, bar);

The problem with defensiveness

void doIt(Foo foo, Bar bar) {
  if (bar == null) { // y'know because null happens!
    // code that doesn't use bar
  } else {
    // code that use it
  }
}

Look Ma, I'm a defensive programmer

Are you sure
null just happens?

Whenever you are defensive ask yourself: 
when should that parameter be null.

// code
Bar bar = service.getIt();
doIt(foo, bar);

Are you expecting getIt() to return null?

  • If answer is "no", then you don't need to be defensive!

  • If answer is "yes" and you expect it, then use an if/else to call the method that doesn't use the parameter!

Being defensive doesn't mean that you have to
code blindly

void doIt(Foo foo, Bar bar) {
   java.util.Objects.requireNonNull(foo);
   java.util.Objects.requireNonNull(bar);
   // more code
}

Now that you don't need to be defensive, you still need to validate parameters

Objects is part of the Java API
since 1.7. Can't use that version?
Use Guava Preconditions!

Basz(Foo foo) {
   this.foo = Objects.requireNonNull(foo);
   // more code
}

You may even use the return value in assignments

Always validate your parameters in the first lines of code, so you fail-fast!

Step #2

Never return null

You don't return
null because the caller
of the method may not realize its getting one

But some methods need a way to signal an absence of a value!

You can do a try-or-else method

String getValueOrElse(Foo foo, String defaultValue) {
   // code
   String value = ...; // I calculate the vale somehow
   return value != null ? value : defaultValue;    
}

Java 8 introduced a getOrDefault method in the Map interface

You can return a null-object

List<Foo> getFoos() {
   // code
   List<Foo> foos = ...; // Get the list of foos
   return foos.size > 0 ? foos : Collections.emptyList();   
}

A null object is an object which state makes it
clear that the object is
"empty" but that it doesn't
break our code

An empty collection
is a null object for
that collection

Creating null objects is
not as easy as following
a formula, almost
every case is unique

Finally you may opt
for Java's Optional
or Guava's Optional

public void run() throws IOException {
  try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(source)) {
    for (Path path : directoryStream) {
      if (Images.isImage(path)) {
        Image image = new Image(path);
        if (image.isProportional(width, height)) {
          image = image.resize(width, height);
          image.write(destination);
        }
      }
    }
  }
}

You can go from this...

public void run() throws IOException {
  try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(source)) {
    for (Path path : directoryStream) {
      Optional.of(path)
              .filter(Images::isImage)
              .map(Image::of)
              .filter(image -> image.isProportial(width, height))
              .map(image -> image.resize(width, height))
              .forEach(Image::write);
    }
  }
}

... to this.

If one of the methods of Optional returns a null, Optional becomes an empty Optional and subsequent operations
are ignored

Optional<Foo> getFoo() {
   // code
}

Method's signature is honest, you know you may not get a foo after all

To avoid returning null

  • Use a "wrapper" get-or-else method
  • Return a Null-Object
  • Return an Optional<T>

There is one more thing... good exception handling

public Foo getFoo(Bar bar) {
  Foo foo = null;
  try {
    foo = bar.something();
  } catch (MyException e) {
    LOGGER.error();
  }
  return foo;
}

Have you seen code like this?

Why do you need a null reference?

ByteArrayOutputStream outputStream = null;
// this need to be visible...
GZIPOutputStream gzipOutputStream = null;

try {
   outputStream = new ByteArrayOutputStream();
   gzipOutputStream = new GZIPOutputStream(outputStream);
   gzipOutputStream.write(data);
   return outputStream.toByteArray();
catch (Exception e) {
   // error handling
} finally {
   if (gzipOutputStream != null) {
      gzipOutputStream.close();  // ...here!!
   }
}

There was only 1
good reason to have null references... resources managment

try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
     GZIPOutputStream gzipOutputStream =new GZIPOutputStream(outputStream)) {
   gzipOutputStream.write(data);
   return outputStream.toByteArray();
catch (Exception e) {
  // error handling
} 

Since Java 7, that's no longer the case

But, bad habits die hard, so people used null references before a try statement even if they don't need them, and IDE's have part of the blame!

void something() {
  Foo foo = getFoo(); // this throws an exception
}

As soon as you type this...

your IDE shows a compiler error

void something() {
  Foo foo = null;
  try {
    foo = getFoo(); // this throws an exception
  } catch (MyException e) {

  }
}

If you choose "surround with try/catch", the results is always

Why?!, Why?!

Don't always trust blindly your IDE or
a coworker!

Your try statement should be your fist line of code

Your catch statement should be the last

(remember, since
Java 7 you don't need finally statements)

void doIt() {
  try { // no code before

  } catch (MyException e) {

  } // no code after
}
Foo getFoo(Bar bar) {
  try {
    Foo foo = bar.something();
    return foo;
  } catch (MyException e) {
    throw new AssertionError(e);
  }
}

It should be like this...

Optional<Foo> getFoo(Bar bar) {
  try {
    Foo foo = bar.something();
    return Optional.of(foo);
  } catch (MyException e) {
    return Optional.empty();
  }
}

or...

void doIt(Bar bar) {
  try {
    Foo foo = bar.something();
    foo.amazeMe();
  } catch (MyException e) {
    LOGGER.info("This failed");
  }
}

or...

Foo getFoo(Bar bar) throws MyException {
  Foo foo = bar.something();
  return foo;
}

or...

Don't catch an exception blindly! Give some
thought on your error handling strategy.

Instead of returning null

  • Propagate the exception
  • Throw an AssertionError
  • Change the signature to return Optional

Step #3

Never instantiate to null

So we come back to the origin of null

Never introduce

a variable when

you don't have a value for it

But there are some
very common uses of a variable initialized to null

Foo something = null;
if (/* a contional */) {
   something = ...;
} else {
   // complex code
   something = ...;
}
// code that uses something

Can we avoid the null reference?

Culprit #1

Foo something = /* a contional */ ? value 1 : value 2; 
// code that uses something
Foo something = /* a contional */ ? value 1 : get(); 
// code that uses something
Foo something = get();
* * *
Foo get() {
  if (/* a conditional */) {
    return value 1;
  }
  // complex code to calculate value
  return value 2
}

Avoid null

  • Use the tertiary operator 
  • Use functions
  • Use combination of both
public T fullMonty() {
   T obj = null;
   try {
      // code
   } catch (ABCException e) {
      // code
   }
   return obj;
}

Culprit #2: The Big One

Can we avoid the null reference?

It's not clear if the intention is to return null or not

Clean Code's recipe

  • There is no code before
    the try statement
  • There is no code after
    the last catch statement
  • Have a public method that
    only has error handling code
  • Have a private method that
    throws exceptions and have
    only logic
public T fullMonty(/* params */) {
   try {
      return doFullMonty(/* params */);
   } catch (ABCException e) {
      // error handling code
      // here you have visibility
      // of all params
   }
}
private T doFullMonty(/* params */) throws ABCException {
   // simple code
   return tValue;
}
public T fullMonty() {
   T obj = null;
   try {
      // code
   } catch (ABCException e) {
      // code
   }
   return obj;
}

You can go from this ...

public Optional<T> fullMonty(Bar bar) {
   try {
      return Optional.of(doFullMonty(bar));
   } catch (ABCException e) {
      LOGGER.error("Full monty failed on {}", bar);
      return Optional.empty();
   }
}

to this...

private T doFullMonty(Bar bar) throws ABCException {
   // easy to understand code
   return tValue;
}

Avoid using null

  • foo public method with error handling code
  • doFoo private method throws exception has easy to understand code
  • no code before try statement and no code before last catch statement
String line = null;
while ((line = br.readLine()) != null) {
   // do something with line
}

Culprit #3: Legacy Code

Can we avoid the null reference?

String line = br.readLine();
while (line != null) {
   // do something with line
   line = br.readLine();
}

If you saw code like this, it doesn't

mean that you have to used as is

Avoid null

  • Don't copy/paste bad code, improve it
  • Try to use modern libraries
  • If using legacy code you end with null in
    conditionals that's ok ...
  • ... if not, create wrapper methods

Let's make a vow!

Because this is not funny!

The best way to eliminate NPE is to get rid of null!

I vow, to the best
of my possibilities

  • to relegate null to an implementation detail
  • to refactor code that I use to not use null anymore
  • to explain to others why those ideas are important

References

Q&A

Thanks!

@gaijinco
gaijinco@gmail.com

KILL NULL

By Carlos Obregón

KILL NULL

Best practices on how to write code that doesn't use null at all

  • 1,976