Re: toward null-safe cookie cutter Comparators
On 11/14/11 10:28 AM, Roedy Green wrote:
On Sun, 13 Nov 2011 17:59:54 +0000, Tom Anderson
<twic@urchin.earth.li> wrote, quoted or indirectly quoted someone who
said :
return aSpecies.compareTo( bSpecies );
Perhaps even pushing the duplicated denullification into a little method.
Note that when the Elvis operator makes it into Java, you will be able to
write:
This whole business of multiple representations for empty.
Acch(Imagine a Yiddish sound of contempt).
null, "", " "
I have have always felt this looseness was like a trap a child digs to
catch the mailman.
There are no assertions defining what a given method parm will accept
(though IntelliJ is pushing @Nullable and #NotNull) There is not even
a JavaDoc convention to warn you if a method might produce which
combinations of the three.
see http://mindprod.com/jgloss/empty.html
From a machine efficiency point of view, null is probably the best
convention. Empty is usually a special case anyway. It might as well
be easy to detect.
From a coding safety point of view "" is best. It will generaly work
sensibly if passed to a method expecting a substantial string, where
there is a good chance it would fail on null.
The real problem is handling User Input and Form Submission. The empty
string ("") signifies that a field was submitted but not filled with any
value. A null value signifies that the field was not submitted at all.
Unfortunately when processing such forms the null value, an empty
string, and an all whitespace string, usually need to be treated the
same way. Invalid input.
The truth of the matter is that should all be handled by the
binding/validation layer, and then normalized to exactly one such value
(possibly null). Often they should be converted to a domain object
anyway, rather than kept as "just a string".
Maybe we need some sort of Generics to declare what methods
produce/consume and have thecompiler tell you if you are potentially
doing something dangerous at compile time.
I once drove my boss nearly to distraction, because I was convinced
the problem with the project was random empty string representations.
I've seen projects where a *core* library had a method "isNull" defined
thusly:
public boolean isNull(Object o) {
if (o == null) return true;
String s = String.valueOf(o);
if (s.trim().length == 0) {
return true;
}
if ("null".equals(s)) return true;
if ("(null)".equals(s)) return true;
}
Obviously, someone was told that "null" and "(null)" were appearing
somewhere and causing problems. Instead of tracking down the source,
they littered the codebase with these "isNull" checks. I should have my
legal name changed to "Null Null", and see how many forms on the web
reject my name :-)
The DWIM school of thinking
Way back I wrote suggesting a DWIM approach to taming the dreaded
NullPointerException. It is inspired more by scripting languages.
Thing a = null.
a.getAString() --> null
a.getTemp() --> 0.0d;
a.getDufusOBject --> null
a.doSomething() --> does nothing
a.doSomethingElse ( engage( 42 ) ); --> invokes engage function
( in my mind checking a and store come after RHS evaluation,
If I had my way Java would a much stricter left to right
evaluation order)
NPE is one of the best things that can happen. It tells you immediately
what needed to have a value but didn't. Rather than the end result of a
chain of null operations that failed deeply in the project.
Imagine the following:
// Commonly used library method handleThing.
void handleThing(Thing t) {
AnotherThing at = t.getAnotherThing()
doSomething(at);
}
void doSomething(AnotherThing t) {
saveToDatabase(t.getName(), t.getId());
}
Now, imagine you get a database error (or worse, no error, just bad null
records). You have *no* trace whatsoever of which call of handleThing
caused the problem. This is similar to the potential problem caused by
NaN propagation.
For more explicit use, you would replace the . operator with .? to
indicate you wanted to do a dummy var fetch/method call or none at all
if "a" were null. When I thought about extending that I though
perhaps classes should use dummy objects in place of null to bypass
this sort of trouble at clealr all that null-handling clutter,just
letting the null-handling logic come out in the wash most of the
time.
The thinking is a bit like the way there are are multiple flavours of
NaN in IEEE floating point, and the value appearing in calculation is
not the end of the world. The null just propagates.
P.S.
Apparently the eponymous Elvis rarely went to Las Vegas. I have not
tracked down who he is. People were often puzzled when I talked about
the McCarthy or operator || the bitwise | one.
see http://mindprod.com/jgloss/or.html The McCarthy I refer to
probably never met Candice Bergen and died recently.