Friday, November 8, 2013

Returning null is the devil, never do it

This, first of all, goes mainly for object oriented languages. In C, you have no option but to return null.

I'm on a bit of a personal crusade against functions that "return null;" Allow me to soapbox a bit.

So many perfectly avoidable bugs arise from this practice. Sure, the exception will probably be called somewhere higher up in the code, and things probably won't be that bad. Unless someone has written a function like say

If your function can fail, and you expect the caller to deal with it, you should throw a checked exception. That way, the caller will deal with it. And if he doesn't, he's explicitly ignored an exception, and he's a moron. If you fail and don't think your caller will be able to deal with it, throw an unchecked exception on the spot. Returning null and having the caller explode at some unspecified time later isn't cool, not one bit. You should fail fast, and make as loud a bang a possible.

If your function can fail, and you communicate this by returning null, the caller may not null check. It's an easy mistake to make. Oftentimes, you need to thoroughly investigate the function being called before even finding how it returns null -- it may happen in something it calls.

Of course, sometimes null isn't an error, but an absence of data. In that case, always return a safe object. Like an empty list, an empty string, and so on. If someone doesn't have a name set, his name isn't null, it is "". If you ask me how many green skinned people live in my neighborhood, I don't say null, I give you an empty list.

Which is why I propose the following strategy to seeing "return null;". Get mad. This function lied to you. It betrayed you. You trusted it, and it rewarded you by stabbing you in the back. It told you it would bring you an object, but it gave you nothing. That bastard! You should be livid at this.

Null-checking is a symptom of bad code, and is a bad solution to the problem at that. The problem at heat is that null checking is very easy to overlook. You oftentimes have to have the code crash before you realize a return value could be null. If you are relying on trial-and-error to make your code stable, you are doing something terribly wrong. Furthermore, a function littered with null checks is significantly more hard to read and maintain, not to mention, if it has 17 null checks already, you almost certainly won't know if it needs another one by looking at it. The very fact that null checks are easily overlooked is reason enough to avoid returning null -- who knows when and how that will backfire. You don't want to be the next Knight Capital. KC's problems weren't down to a NPE, but to a slew of other bad practices, but in a wider sense it's all the same.

The fix to this problem isn't to add null checks, but to re-write the poorly designed function(s). If that isn't possible because it's 3rd party or legacy code, call it indirectly through a facade that guarantees proper error handling.

No comments:

Post a Comment