I guess everybody has a story or two in store about Nullpointer
exceptions in Java (or in any language with nullable values). Sooner or later you will make the acquaintance of the dreaded stacktrace line
denoting that you did something terribly wrong, demanding a value
where none exists, and you just wonder why, how the hell can that
object be null?! during an hour of painful debugging… you know
that? Good. Well, I won’t ponder over how to avoid it, how to apply
proper error handling etc. (that’s way too complicated, I’m tired) but I’d just like to point out my personal
favourite, the
famous else return null
idiom.
Anyway, the below snippet shows what I actually mean by that.
1 2 3 4 5 6 7 8 9 10 11 |
|
To make things more familiar, in Version 2 you could imagine multiple return null
lines hidden in
various control structures in an endless method and you surely get an idea
how people feel when they try to reason about an object being null
or not.
Anyway, spotting an else return null
I always get a bad gut feeling
saying that things are not what they are supposed to be. I’m aware
that this obviously touches upon the question if you should avoid
null values altogether. Anyway, I can’t help my bad gut feeling
whenever I see it ;)
The funny thing is that I recently wrote similar code myself; that
alone would not be a surprise yet, but I actually wrote it in
Haskell which does not have that notion of null values and the
corresponding Nullpointer exception. In Haskell, there is the Maybe monad which facilitates chaining “partial” computations together without
the risk of a Nullpointer exception. Here is the snippet of that code
(obviously, only the else Nothing
is ‘important’).
1 2 3 4 5 6 |
|
Anyway, believe me, if you ever write such an else Nothing
in Haskell, that should
be the trigger – take a deep breath, take a coffee and think about your
problem again. At the least, you are overcomplicating things as using
the Monad or MonadPlus nature of Maybe would make life easier
but probably it’s an indication that your thoughts are about to go
astray and you get lost in old else return null
habits or worse – so better
stop it and take a break!
How would the MonadPlus and Monad instances make life better? Look at the below version. In any case, it’s functionally equivalent, so how would it be ‘better’? In my opinion, it conveys much more the impression that the programmer actually knows what they are doing.
1 2 3 4 5 |
|
Essentially, the guard
function does the trick. guard
, which has the type
guard :: MonadPlus m => Bool –> m (), makes the containing do
block evaluate to Nothing
if the Bool
argument evaluates to
False
. In that sense, the guard
expression actually looks like an
assertion! The whole MonadPlus magic can be further explored here.
In my case, I finally ended up removing those lines altogether. As suspected, the
good old else Nothing
was the symptom that I had lost track of
what I was coding at all – completely lost in nothingness – and I really needed a
break.
So what is your typical ‘silly code’ that you typically start writing when you should rather take a break?