vendredi 16 octobre 2015

Null pointer exceptions

Every developer has ever face a null pointer or null reference exception (NPE) in her or his life. It’s likely to occur from anywhere in your code and you fear to see it occur during an important demo or while your app is alive.

Let’s recall what it is and why it occurs, for the few readers that might not know what I’m talking about. NPE is a runtime exception that occurs when you’re trying to call a member of null value, making the assumption it’s an actual object. Classical example in Java, where == does not compare string values :

String foo = null;
return foo.equal("bar"); // boom, should have done "bar".equal(foo)!!!

Real situations are not that simple. We’re facing this problem because the type system in most popular languages is not strict enough. It allows functions to return null instead of an instance of the type we’re expecting. That’s right folks: our lovable languages fool ourselves. The obvious solution is to be a defensive maniac, testing null every time you get an object, thus transforming your code base into an awful amount of nullity testing, instead of expressing the behaviour you attend to put in place. Don’t do that. Be smart to mitigate the risk in your system while keeping enjoying clean readable code.

The easy part is iterables. When you return an iterable, return an empty one instead of null, so that caller can iterate on it without a doubt. You cannot justify returning null instead of an empty iterable: think of it as a rule of thumb.

When you return an unique, non iterable object you have to deal with the absence of value. There are 2 causes for returning an empty thing:

  • It’s due to an error in the system. The database is down, the service you call is unavailable. It is an exceptional behaviour, so handle it as a business exception. You won’t have to deal with null return.
  • It is empty for an expected reason. There is no information available and it’s OK. In that case, consider the Null Object pattern to return an empty object that still corresponds to expected interface.

Sometimes, you deal with beans or Data Transfer Objects (DTOs). DTOs are data structures without any behaviours, providing full public access to data through accessors. These objects are what you get when you query a datastore with your favourite ORM (or ODM, nowadays), they are what you get when you deserialize a web service request or response, either when it is SOAP or JSON stream. It happens that you’ll get deeply nested data structures, where some element can be null. Imagine you have a generic insurance system (for house, car, health,…), you want to retrieve a customer vehicle model from a DTO aggregates coming from your DB:

String model = Customer.getVehicle().getModel();

Guess what happens if your customer has no car?

The main risk here is to carry DTOs along your system and keep testing for nullity to access every data from them. First of all, you have the risk to forget a test (and you or someone in your team will forget one), then you have a unreadable code base (see above), and finally you have a sloppy system where you deal with primitive types (string, int, date if your lucky) on business objects that provide no behaviour.

You must get rid of them as quickly as you can.

When you have to deal with DTO, build an Anti Corruption layer in the boundaries of your system to integrate them in your smart, well designed, close-to-the-domain object model.

Well designed object model means that, contrary to DTOs, objects hide as much information as they can and rather expose behaviours through their methods. In particular, your design should prevent method chaining, AKA breaking the Law of Demeter. If you want simple rules for object design, you can follow object calisthenics rules (here simple means simple to remember, not simplistic or simple to do).

Conclusion of the article: as developers, we all face Null Pointer or Null Reference exception. That is not a fatality nor something we should fear. With a bit of discipline, you can highly mitigate the risk of their occurring. That remains the keyword of software programming, my friend: discipline.