« Red-Black trees, oh my (part 3) | Main | Dear Null - Feedback »

April 11, 2011

Comments

Feed You can follow this conversation by subscribing to the comment feed for this post.

To avoid this: Never accept null. Never return null.

To help you: Don't use 'getters' - Tell don't ask, but sometimes ask. In this case shirt.isBlue() might work, or even shirt.isColour(Blue), but not shirt.getColour() == Blue.

shirt.isShirtBlue() is probably missing something?

null in java or whatever isn't like SQL's poorly implemented version of a three value logic system, its just a pain - so don't use it.

btw - exposing Maps has a lot of the same problems, so its best not to do that either.

"I call it my billion-dollar mistake. It was the invention of the null reference in 1965. At that time, I was designing the first comprehensive type system for references in an object oriented language (ALGOL W). My goal was to ensure that all use of references should be absolutely safe, with checking performed automatically by the compiler. But I couldn't resist the temptation to put in a null reference, simply because it was so easy to implement. This has led to innumerable errors, vulnerabilities, and system crashes, which have probably caused a billion dollars of pain and damage in the last forty years. In recent years, a number of program analysers like PREfix and PREfast in Microsoft have been used to check references, and give warnings if there is a risk they may be non-null. More recent programming languages like Spec# have introduced declarations for non-null references. This is the solution, which I rejected in 1965." - C.A.R. Hoare

http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+Mistake

The problem you have in languages like e.g. Java or C is that there is no type for a reference which cannot hold null. Various languages have attempted to address this: Scala has Option types (which are a watered-down approach); Nice has better option types [1]; Fantom has nullable types [2]; Whiley has union types [3]; etc.

[1] http://nice.sourceforge.net/manual.html#id2536072
[2] http://fantom.org/sidewalk/topic/369
[3] http://whiley.org/guide/typing/flow-typing

@James - "Never accept null." Ha ha, nice one. "Tell don't ask, but sometimes ask." Seriously?
@Dave - C# also has nullable types, and they may prove useful in this scenario.

How can a function "not accept" null, especially in languages like Oracle SQL where an empty string is effectively identical to null (go ahead, try to insert a zero length string and see what you get)? Seriously, refusal to process nulls means what? Throw an exception or (more likely) simply output another null?

Just use something like Haskell's Maybe, or Scala's Option (which works similarly although isn't as great).

You use a type constructor Maybe and wrap it around your actual type. For example, 'Maybe Bool'. Then, you can either return 'Just True', 'Just False', or 'Nothing'. Maybe is a monad and an applicative functor, so you can do something like '(isFileInUse path >> useFile path) [less than sign]|[greater than sign] fail "file does not exist"'

You might want to fix your HTML stripper, by the way, there seems to be no way to escape less than and greater than signs.

@Patrick - @Allan - Never accept null - If in your program you decide that you simply won't use nulls across class boundaries, then the problem kind of goes away. If you simply don't null check, then as soon as you get a null, it means a software defect. i.e. you don't accept them. As soon as you pass a null to a method, it will fail with a NPE, but thats OK, because it now means a real bug. You now need to track down where the null came from, and make sure that whoever passed that null passes an object out instead, or maybe refactor your inter-object collaborations a bit.

Tell don't ask, but sometimes ask. I'm assuming you know of 'tell don't ask', if you are writing about OO! I gave an example of where you might want to ask... hence sometimes ask! - read http://pragprog.com/articles/tell-dont-ask http://www.growing-object-oriented-software.com/toc.html

@Allan - If you read what I wrote, then you will see that I said 'never return null', so not sure how you can interpret that to be 'simply output another null'.

There are lots of patterns you can use to help you, including polymorphism, 'tell don't ask', null object, and other stuff that mean this is totally doable.

@James - Please do not confuse my satire for anything more or less than just that. Your "but sometimes ask" comment was just funny when preceded by "don't ask", funny in a grammatical sense. Check out my follow-up post (I've updated this post with a link). As far as "this is totally doable", I'm afraid you may have missed my point. I just found something I though was funny and thought I would write about what I saw. Call it "observational humor". I appreciate your input!

You're making things too complicated, for what reason I know not, perhaps to have something to write about.

For example, the first function IsShirtBlue you chose to interpret as "this is a shirt, is it blue?", and based on this interpretation you chose to discredit the notion of a NULL variable when it was supplied as an argument to the function accepting a shirt.

If you chose to interpret that function as "is this a blue shirt?" then your entire argument is moot. Supplying NULL would return false since it is not even a shirt, and if it is a shirt it would return whether it is blue or not.

When you construct a function you also design the contract under which that function is used. If you imply that it can not accept a NULL value because the function then wouldn't make sense, then don't blame NULL when you break that contract.

@Lukasz - Your concept of a function's contract is wrong. The contract represented by IsShirtBlue is (Shirt) -> (Bool). The name of the function is irrelevant. Supplying NULL to this function does not break its contract and that point was never made nor implied in my post.

The point is "IsShirtBlue" (or if you would prefer "IsThisABlueShirt", or if I prefer "ThisDoesNotMatter") is a vacuous truth when given a NULL shirt. In this case a return value of "false" will carry ambiguity since it does not differentiate between NULL and a shirt that is not blue.

Also, your implication about me making things complicated to have something to write about is quite wrong.

The comments to this entry are closed.