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?