3 May 2005 23:10
Re: Passing null around in a system
John Carter <john.carter <at> tait.co.nz>
2005-05-03 21:10:37 GMT
2005-05-03 21:10:37 GMT
On Tue, 12 Apr 2005, Vijay Baliga wrote:
> Don't pass null in production code unless you have no other choice. I know
> that some libraries out there expect you to, but when you write fresh code
> there are better alternatives. If you are tempted to use null in production
> code, find the places where you are returning nulls and passing nulls, and
> consider a different protocol. Consider using the Null Object Pattern
> instead.
This caused me to go an look at my code and contemplate cases where I
use nil. (I'm speaking Ruby which has the following special
properties....
* Like C++ it allows you to specify default values for parameters.
* nil === false, everything else is true.)
Thus the most common case where I use a nil parameter is as a default parameter
for example....
def issue_command( command, description = nil)
description = "Do #{command}" unless description
...
end
If the user doesn't set the description, the description is just set
to "Do XXX" where XXX is the command issued. (Ok, lame example, but
you get the general principle, the real cases are substantially more
complex.)
The other pattern is to switch behaviour in and out. If the routine is
expected to perform some variant processing as described by a
parameter, I could do....(speaking C)
void do_stuff( bool_t doExtraStuff, int extraStuffParameter) {
...
if (doExtraStuff) {
// use extraStuffParameter
}
...
}
In ruby I tend to do...
def do_stuff( extraStuff = nil)
....
if extraStuff
// Use extraStuff
end
...
end
Sure I could use a NullObject pattern, but in these cases I didn't
(don't) feel it is worth spinning an extra class just for 5 lines of
code.
The refactoring I prefer in these cases is to split do_stuff, this is
especially effective if the "if extraStuff" is either at the front or
the back of do_stuff, and doesn't contain any local variables of do_stuff. ie.
Take out the "if extraStuff" and move it into the calling code. So the
invocation becomes either...
do_stuff
do_extra_stuff( extraStuffParameter)
or just plain...
do_stuff
depending on what I mean.
However, sometimes (rarely) the extra stuff is really deeply embedded
within "do_stuff" and cannot sensibly be extracted. So I leave it and
use a null default parameter.
I see I also use a curious subcase of the NullObject pattern.
def find_files( matching_regex = /./)
...
end
ie. The default is a regex that will match all files.
John Carter Phone : (64)(3) 358 6639
Tait Electronics Fax : (64)(3) 359 4632
PO Box 1645 Christchurch Email : john.carter <at> tait.co.nz
New Zealand
Somewhere on the edge of a Galaxy, one of literally billions of such
galaxies, is a sun, one of literally billions of suns in that
galaxy.
Orbiting that sun is a small rock 330000 times smaller than that
sun.
This rock is covered by a very very thin scum of life. (Think 6000km
of rock followed by a meter or so of biomass.)
Amongst the millions of species in that scum are many hundreds of
thousands of types beetle and a mere handful of primates.
Surprisingly enough, this email does not originate from a beetle.
It originates from just one of the 6 billion vastly outnumbered humans.
I trust you will keep this perspective and context in mind when
reacting to this email.
Yahoo! Groups Links
<*> To visit your group on the web, go to:
http://groups.yahoo.com/group/refactoring/
<*> To unsubscribe from this group, send an email to:
refactoring-unsubscribe <at> yahoogroups.com
<*> Your use of Yahoo! Groups is subject to:
http://docs.yahoo.com/info/terms/
RSS Feed