Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I've heard it said that the inclusion of null references in programming languages is the "billion dollar mistake". But why? Sure, they can cause NullReferenceExceptions, but so what? Any element of the language can be a source of errors if used improperly.

And what's the alternative? I suppose instead of saying this:

Customer c = Customer.GetByLastName("Goodman"); // returns null if not found
if (c != null)
{
    Console.WriteLine(c.FirstName + " " + c.LastName + " is awesome!");
}
else { Console.WriteLine("There was no customer named Goodman.  How lame!"); }

You could say this:

if (Customer.ExistsWithLastName("Goodman"))
{
    Customer c = Customer.GetByLastName("Goodman") // throws error if not found
    Console.WriteLine(c.FirstName + " " + c.LastName + " is awesome!"); 
}
else { Console.WriteLine("There was no customer named Goodman.  How lame!"); }

But how is that better? Either way, if you forget to check that the customer exists, you get an exception.

I suppose that a CustomerNotFoundException is a bit easier to debug than a NullReferenceException by virtue of being more descriptive. Is that all there is to it?

share|improve this question
29  
I'd be wary of the "if Customer exists / then get Customer" approach, as soon as you write two lines of code like that, you're opening the door for race conditions. Get, and then check for nulls / catch exceptions is safer. –  Carson63000 Oct 19 '10 at 2:48
15  
If only we could eliminate the source of all runtime errors, our code would be guaranteed to be perfect! If NULL references in C# break your brain, try invalid, but non-NULL, pointers in C ;) –  LnxPrgr3 Oct 19 '10 at 5:44
12  
null per se isn't bad. A type system that makes no difference between type T and type T+null is bad. –  Ingo Mar 12 at 22:26
9  
Coming back to my own question a few years later, I'm now totally a convert of the Option / Maybe approach. –  Tim Goodman Mar 13 at 20:16

21 Answers 21

up vote 47 down vote accepted

null is evil

There is a presentation on InfoQ on this topic: Null References: The Billion Dollar Mistake by Tony Hoare

Option type

The alternative from functional programming is using an Option type, that can contain SOME value or NONE.

A good article The “Option” Pattern that discuss the Option type and provide an implementation of it for Java.

I have also found a bug-report for Java about this issue: Add Nice Option types to Java to prevent NullPointerExceptions.

share|improve this answer
4  
Nullable<x> in C# is a similar concept but falls way short of being an implementation of the option pattern. The main reason is that in .NET System.Nullable is limited to value types. –  MattDavey Jul 13 '12 at 17:47
13  
+1 For the Option type. After getting familiar with Haskell's Maybe, nulls start looking weird... –  Andres F. Jul 13 '12 at 17:53
4  
Developer can make error anywhere, so instead of null pointer exception you will get empty option exception. How the latter is better than the former? –  greenoldman May 22 '13 at 13:24
5  
@greenoldman there is no such thing as "empty option exception". Try inserting NULL values into database columns defined as NOT NULL. –  Jonas May 22 '13 at 15:58
12  
@greenoldman The problem with nulls is that anything can be null, and as a developer you have to be extra cautious. A String type isn't really a string. It's a String or Null type. Languages that fully adhere to the idea of option types disallow null values in their type system, giving a guarantee that if you define a type signature that requires a String (or anything else), it must have a value. The Option type is there to give a type-level representation of things that may or may not have a value, so you know where you must explicitly handle those situations. –  KChaloux Mar 13 at 15:01

The problem is that because in theory any object can be a null and toss an exception when you attempt to use it, your object-oriented code is basically a collection of unexploded bombs.

You're right that graceful error handling can be functionally identical to null-checking if statements. But what happens when something you convinced yourself couldn't possibly be a null is, in fact, a null? Kerboom. Whatever happens next, I'm willing to bet that 1) it won't be graceful and 2) you won't like it.

And do not dismiss the value of "easy to debug." Mature production code is a mad, sprawling creature; anything that gives you more insight into what went wrong and where may save you hours of digging.

share|improve this answer
19  
+1 Usually errors in production code NEED to be identified as fast as possible so they can be fixed (usually data error). The easier it is to debug, the better. –  user1249 Oct 18 '10 at 20:46
2  
+1 Very good points. I never even thought of it that way. (ie I've never really had this debate before, and always took null references as a given, as a C/C++/Java person). –  Bobby Tables Oct 18 '10 at 21:13
12  
+1 for unexploded bombs. With null references, saying public Foo doStuff() doesn't mean "do stuff and return the Foo result" it means "do stuff and return the Foo result, OR return null, but you have no idea if that will happen or not." The result is that you have to null check EVERYWHERE to be certain. Might as well remove nulls and use a special type or pattern (like a value type) to indicate a meaningless value. –  Matt Olenik Oct 19 '10 at 18:25
5  
@greenoldman, your example is doubly effective to demonstrate our point in that the use of primitive types (whether null or integers) as semantic models is poor practice. If you have a type for which negative numbers isn't a valid answer, you should create a new class of types to implement the semantic model with that meaning. Now all the code to handle the modeling of that non-negative type is localized to its class, isolated from the rest of the system, and any attempt to create a negative value for it can be caught immediately. –  Huperniketes May 26 '13 at 4:10
5  
@greenoldman, you continue to prove the point that primitive types are inadequate for modeling. First it was over negative numbers. Now it's over the division operator when zero is the divisor. If you know you can't divide by zero then you can predict the outcome isn't going to be pretty, and are responsible for ensuring you test for, and provide the appropriate "valid" value for that case. Software developers are responsible for knowing the parameters in which their code operates, and coding appropriately. It's what distinguishes engineering from tinkering. –  Huperniketes Jun 6 '13 at 10:17

There are several problems with using null references in code.

First, it's generally used to indicate a special state. Rather than defining a new class or constant for each state as specializations are normally done, using a null reference is using a lossy, massively generalized type/value.

Second, debugging code becomes more difficult when a null reference appears and you attempt to determine what generated it, which state is in effect and its cause even if you can trace its upstream execution path.

Third, null references introduces additional code paths to test.

Fourth, once null references are used as valid states for parameters as well as return values, defensive programming (for states caused by design) requires more null reference checking to be done in various places…just in case.

Fifth, the language's runtime is already performing type checks when it performs selector lookup on an object's method table. So you're duplicating effort by checking if the object's type is valid/invalid and then having the runtime check the valid object's type to invoke its method.

Why not use the NullObject pattern to take advantage of the runtime's check to have it invoke NOP methods specific to that state (conforming to the regular state's interface) while also eliminating all the extra checking for null references throughout your codebase?

It involves more work by creating a NullObject class for each interface with which you want to represent a special state. But at least the specialization is isolated to each special state, rather than the code in which the state might be present. IOW, the number of tests are reduced because you have fewer alternate execution paths in your methods.

share|improve this answer
4  
+1 for suggesting the Null Object pattern. –  Frank Shearar Oct 18 '10 at 21:12
3  
...because figuring out who generated (or rather, didn't bother to change or initialize) the garbage data that is filling your supposedly useful object is so much easier than tracking a NULL reference? I don't buy it, although I'm mostly stuck in statically typed land. –  dash-tom-bang Oct 19 '10 at 0:00
1  
-1 for Null Object. –  DeadMG Jul 13 '12 at 22:18
1  
Points (4) and (5) are solid, but the NullObject is not a remedy. You will fall into even worse trap -- logic (workflow) errors. When you know EXACTLY the current situation, sure, it can help, but using it blindly (instead of null) will cost you more. –  greenoldman May 22 '13 at 13:29

Nulls aren't so bad, unless you're not expecting them. You should need to explicitly specify in code that you're expecting null, which is a language-design problem. Consider this:

Customer? c = Customer.GetByLastName("Goodman");
// note the question mark -- 'c' is either a Customer or null
if (c != null)
{
    // c is not null, therefore its type in this block is
    // now 'Customer' instead of 'Customer?'
    Console.WriteLine(c.FirstName + " " + c.LastName + " is awesome!");
}
else { Console.WriteLine("There was no customer named Goodman.  How lame!"); }

If you try to invoke methods on a Customer?, you should get a compile-time error. The reason more languages don't do this (IMO) is that they don't provide for the type of a variable to change depending on what scope it's in. If the language can handle that, then the problem can be solved entirely within the type system.

There's also the functional way to handle this problem, using option-types and Maybe, but I'm not as familiar with it. I prefer this way because correct code should theoretically only need one character added to compile correctly.

share|improve this answer
4  
Wow, that's pretty cool. In addition to catching a lot more errors at compile time, it spares me from having to check the documentation to figure out whether GetByLastName returns null if not found (as opposed to throwing an exception) -- I can just see if it returns Customer? or Customer. –  Tim Goodman Oct 18 '10 at 19:37
9  
@JBRWilkinson: This is just a cooked-up example to show the idea, not an example of an actual implementation. I actually think it's a pretty neat idea. –  Dean Harding Oct 18 '10 at 23:12
1  
You're right that it's not the null object pattern, though. –  Dean Harding Oct 18 '10 at 23:15
7  
This looks like what Haskell calls a Maybe -- A Maybe Customer is either Just c (where c is a Customer) or Nothing. In other languages, it's called Option -- see some of the other answers on this question. –  MatrixFrog Aug 22 '11 at 18:38
1  
@SimonBarker: you can be sure if Customer.FirstName is of type String (as opposed to String?). That's the real benefit - only variables/properties that have a meaningful nothing value should be declared as nullable. –  Yogu May 2 at 16:17

Null references are a mistake because they allow non-sensical code:

foo = null
foo.bar()

There are alternatives, if you leverage the type system:

Maybe<Foo> foo = null
foo.bar() // error{Maybe<Foo> does not have any bar method}

The generally idea is to put the variable in a box, and the only thing you can do is unboxing it, preferably enlisting the compiler help like proposed for Eiffel.

Haskell has it from scratch (Maybe), in C++ you can leverage boost::optional<T> but you can still get undefined behaviour...

share|improve this answer
5  
-1 for "leverage"! –  Mark C Oct 18 '10 at 19:17
5  
But surely lots of common programming constructs allow for nonsensical code, no? Division by zero is (arguably) nonsensical, but we still allow division, and hope the programmer remembers to check that the divisor is non-zero (or handle the exception). –  Tim Goodman Oct 18 '10 at 20:14
3  
I'm not certain what you mean by "from scratch", but Maybe isn't built into the core language, its definition just happens to be in the standard prelude: data Maybe t = Nothing | Just t. –  FredOverflow Oct 18 '10 at 21:28
3  
@FredOverflow: since the prelude is loaded by default, I would consider it "from scratch", that Haskell has a astonishing enough type system to allow this (and other) niceties to be defined with the general rules of the language is just a bonus :) –  Matthieu M. Oct 20 '10 at 15:00
1  
@greenoldman: You would have some way to pattern match on the Maybe<A> value (ie do this when it has a value and that when it's null). Most languages can include this in a library with first-class functions and lambdas, and many languages have specific constructs for pattern-matching like this (ie switch on steroids). –  Tikhon Jelvis Aug 26 at 18:32

And what's the alternative?

Optional types and pattern matching. Since I don't know C#, here is a piece of code in a fictional language called Scala# :-)

Customer.GetByLastName("Goodman")    // returns Option[Customer]
match
{
    case Some(customer) =>
    Console.WriteLine(customer.FirstName + " " + customer.LastName + " is awesome!");

    case None =>
    Console.WriteLine("There was no customer named Goodman.  How lame!");
}
share|improve this answer

The problem with nulls is that languages that allow them pretty much force you into programming defensively against it. It takes a lot of effort (far more than trying to use defensive if-blocks) to make sure that

  1. the objects you expect them not to be null are indeed never null, and
  2. that your defensive mechanisms indeed deal with all potential NPEs effectively.

So, indeed, nulls end up being a costly thing to have.

share|improve this answer
1  
It might be helpful if you included an example where it takes a lot more effort to deal with nulls. In my admittedly over-simplified example the effort is about the same either way. I'm not disagreeing with you, I just find specific (pseudo)code examples paint a clearer picture than general statements. –  Tim Goodman Oct 18 '10 at 20:10
2  
Ah, I didn't explain myself clearly. It is not that it is more difficult to deal with nulls. It is that it is extremely difficult (if not impossible) to guarantee that all access to potentially null references are already safe-guarded. That is, in a language that allows null references, it is just impossible to guarantee that a piece of code of arbitrary size is free of null pointer exceptions, not without through some major difficulties and efforts. That's what make null references an expensive thing. It is extremely expensive to guarantee complete absence of null pointer exceptions. –  luis.espinal Oct 19 '10 at 0:52

There's plenty of excellent answers that cover the unfortunate symptoms of null, so I'd like to present an alternative argument: Null is a flaw in the type system.

The purpose of a type system is to ensure that the different components of a program "fit together" properly; a well-typed program can't "off the rails" into undefined behavior.

Consider a hypothetical dialect of Java, or whatever your preferred statically-typed language is, where you can assign the string "Hello, world!" to any variable of any type:

Foo foo1 = new Foo();  // Legal
Foo foo2 = "Hello, world!"; // Also legal
Foo foo3 = "Bonjour!"; // Not legal - only "Hello, world!" is allowed

And you can check variables like so:

if (foo1 != "Hello, world!") {
    bar(foo1);
} else {
    baz();
}

There's nothing impossible about this - someone could design such a language if they wanted to. The special value need not be "Hello, world!" - it could've been the number 42, the tuple (1, 4, 9), or, say, null. But why would you do this? A variable of type Foo should only hold Foos - that's the whole point of the type system! null is not a Foo any more than "Hello, world!" is. Worse, null is not a value of any type, and there's nothing you can do with it!

The programmer can never be sure that a variable actually holds a Foo, and neither can the program; in order to avoid undefined behavior, it has to check variables for "Hello, world!" before using them as Foos. Note that doing the string check in the previous snippet doesn't propagate the fact that foo1 is really a Foo - bar will likely have its own check as well, just to be safe.

Compare that to using a Maybe/Option type with pattern matching:

case maybeFoo of
 |  Just foo => bar(foo)
 |  Nothing => baz()

Inside the Just foo clause, both you and the program know for sure that our Maybe Foo variable truly does contain a Foo value - that information is propagated down the call chain, and bar doesn't need to do any checks. Because Maybe Foo is a distinct type from Foo, you're forced to handle the possibility that it could contain Nothing, so you can never by blindsided by a NullPointerException. You can reason about your program much more easily and the compiler can omit null checks knowing that all variables of type Foo really do contain Foos. Everyone wins.

share|improve this answer

(Throwing my hat in the ring for an old question ;) )

The specific problem with null is that it breaks static typing.

If I have a Thing t, then the compiler can guarantee I can call t.doSomething(). Well, UNLESS t is null at runtime. Now all bets are off. The compiler said it was OK, but I find out much later that t does NOT in fact doSomething(). So rather than being able to trust the compiler to catch type errors, I have to wait until runtime to catch them. I might as well just use Python!

So, in a sense, null introduces dynamic typing into a statically typed system, with expected results.

The difference between that an divide by zero or log of negative, etc. is that when i = 0, it's still an int. The compiler can still guarantee its type. The problem is that the logic mis-applies that value in a way that isn't permitted by the logic ... but if the logic does that, that's pretty much the definition of a bug.

(The compiler can catch some of those problems, BTW. Like flagging expressions like i = 1 / 0 at compile time. But you can't really expect the compiler to follow into a function and ensure that the parameters are all consistent with the function's logic)

The practical problem is that you do a lot of extra work, and add null checks to protect yourself at runtime, but what if you forget one? The compiler stops you from assigning:

String s = new Integer(1234);

So why should it allow assignment to a value (null) that will break de-references to s?

By mixing "no value" with "typed" references in your code, you're putting an extra burden on the programmers. And when NullPointerExceptions happen, tracking them down can be even more time consuming. Rather than relying on static typing to say "this is a reference to something expected," you're letting the language say "this may well be a reference to something expected."

share|improve this answer

The issue to what degree your programming language attempts to prove your program's correctness before it runs it. In a statically typed language you prove that you have the correct types. By moving to default of non-nullable references (with optional nullable references) you can eliminate many of the cases where null is passed and it shouldn't be. The question is whether the extra effort in handling non-nullable references is worth the benefit in terms of program correctness.

share|improve this answer

A null pointer is a tool

not an enemy. You just ought to use 'em right.

Think just minute about how long it takes to find and fix a typical invalid pointer bug, compared to locating and fixing a null pointer bug. It's easy to check a pointer against null. It is a PITA to verify whether or not a non-null pointer points to valid data.

If still not convinced, add a good dose of multithreading to your scenario, then think again.

Moral of the story: Don't throw the kids with the water. And don't blame the tools for the accident. The man who invented the number zero long time ago was quite clever, since that day you could name the "nothing". The null pointer is not so far away from that.


EDIT: Although the NullObject pattern seems to be a better solution than references that may be null, it introduces problems on its own:

  • A reference holding a NullObject should (according to the theory) do nothing when a method is called. Thus, subtle errors can be introduced due to errorneously unassigned references, which now are guaranteed to be non-null (yehaa!) but perform an unwanted action: nothing. With an NPE it is next to obvious where the problem lies. With a NullObject that behaves somehow (but wrong), we introduce the risk of errors being detected (too) late. This is not by accident similar to an invalid pointer problem and has similar consequences: The reference points to something, that looks like valid data, but isn't, introduces data errors and can be hard to track down. To be honest, in these cases I would without a blink prefer an NPE that fails immediately, now, over a logical/data error which suddenly hits me later down the road. Remember the IBM study about cost of errors being a function of at which stage they are detected?

  • The notion of doing nothing when a method is called on a NullObject does not hold, when a property getter or a function is called, or when the method returns values via out. Let's say, the return value is an int and we decide, that "do nothing" means "return 0". But how can we be sure, that 0 is the right "nothing" to be (not) returned? After all, the NullObject should not do anything, but when asked for a value, it has to react somehow. Failing is not an option: We use the NullObject to prevent the NPE, and we surely won't trade it against another exception (not implemented, divide by zero, ...), do we? So how do you correctly return nothing when you have to return something?

I can't help, but when someone tries to apply the NullObject pattern to each and every problem, it looks more like trying to repair one mistake by doing another one. It is without much doubt a good and useful solution in some cases, but it surely isn't the magic bullet for all cases.

share|improve this answer
1  
@JensG in your latest example, does the compiler make you do the null check before every call to t.Something()? Or does it have some way of knowing you already did the check, and not making you do it again? What if you did the check before you passed t in to this method? With the Option type, the compiler knows whether you've done the check yet or not by looking at the type of t. If it's an Option, you haven't checked it, whereas if it's the unwrapped value then you have. –  Tim Goodman Mar 13 at 21:04

The problem isn't so much null, it's that you can't specify a non-null reference type in a lot of modern languages.

For example, your code might look like

public void MakeCake(Egg egg, Flour flour, Milk milk)
{
    if (egg == null) { throw ... }
    if (flour == null) { throw ... }
    if (milk == null) { throw ... }

    egg.Crack();
    MixingBowl.Mix(egg, flour, milk);
    // etc
}

// inside Mixing bowl class
public void Mix(Egg egg, Flour flour, Milk milk)
{
    if (egg == null) { throw ... }
    if (flour == null) { throw ... }
    if (milk == null) { throw ... }

    //... etc
}

When class references get passed around, defensive programming encourages you to check all parameters for null again, even if you just checked them for null right beforehand, especially when building reusable units under test. The same reference could easily be checked for null 10 times across the codebase!

Wouldn't it be better if you could have a normal nullable type when you get the thing, deal with null then and there, then pass it as a non-nullable type to all your little helper functions and classes without checking for null all the time?

Thats the point of the Option solution - not to allow you to switch on error states, but to allow design of functions which implicitly cannot accept null arguments. Whether or not the "default" implementation of types are nullable or non-nullable is less important than the flexibility of having both tools available.

http://twistedoakstudios.com/blog/Post330_non-nullable-types-vs-c-fixing-the-billion-dollar-mistake

This is also listed as the #2 most voted feature for C# -> https://visualstudio.uservoice.com/forums/121579-visual-studio/category/30931-languages-c

share|improve this answer

Optimise for the most common case.

Having to check for null all the time is tedious - you want to be able to just get hold of the Customer object and work with it.

In the normal case, this should work just fine - you do the look up, get the object and use it.

In the exceptional case, where you're (randomly) looking up a customer by name, not knowing whether that record/object exists, you'd need some indication that this failed. In this situation, the answer is to throw a RecordNotFound exception (or let the SQL provider beneath do this for you).

If you're in a situation where you don't know whether you can trust the data coming in (the parameter), perhaps because it was entered by a user, then you could also provide the 'TryGetCustomer(name, out customer)' pattern. Cross-reference with int.Parse and int.TryParse.

share|improve this answer

Exceptions are not eval!

They are there for a reason. If your code is running bad, there is a genius pattern, called exception, and it tells you that some thing is wrong.

By avoiding using null objects you are hiding part of those exceptions. I am not spiking about OP example where he convert null pointer exception to well typed exception, this might actually be good thing as it increase readability. How ever when you take the Option type solution as @Jonas pointed out, you are hiding exceptions.

Than in your production application, instead of exception to be thrown when you are clicking on button to select empty option, nothing just happening. Instead of null pointer exception would be thrown and we would probably get a report of that exception(as in many production applications we have such mechanism), and than we could actually fix it.

Making your code bulletproof by avoiding exception is bad idea, making you code bulletproof by fixing exception, well this the path that I would choose.

share|improve this answer
1  
I know quite a bit more about the Option type now than when I posted the question a few years ago, since I now use them regularly in Scala. The point of Option is that it makes assigning None to something that isn't an Option into a compile-time error, and likewise using an Option as if it has a value without first checking it is a compile-time error. Compile errors are certainly nicer than run-time exceptions. –  Tim Goodman Mar 13 at 19:55
2  
However I agree with the general comment that exceptions (used properly) are not a bad thing, and "fixing" an exception by swallowing it is generally a terrible idea. But with the Option type, the goal is to turn exceptions into compile-time errors, which are a better thing. –  Tim Goodman Mar 13 at 20:01

As long as a reference is NULL it is no good for the programming Logic hence there is no need to proceed. For this simple reason most compilers will not let you use a reference unless it is initialized. A NPE isn't really an Exception it is a logical Error. Compare it with a FileNotFoundException it is beyond the control of an Application but why would someone(your program) want to USE a thing that doesn't exist ?

share|improve this answer

Nullable references are not a problem in and of themselves. However, I reckon nonnullable types (whether references or not) are much more fundamental than nullable ones, and, in any case, constructing a nullable type from its nonnullable counterpart is trivial (using union types, e.g., Haskell's Maybe), while constructing a nonnullable type from its nullable counterpart is much harder.

share|improve this answer

I saw this quote a while ago:

If null was allowed in natural languages, every noun would be interpreted with an implicit "or not" with it.

share|improve this answer
1  
this sould be a comment –  Simon May 2 at 15:47

If it will be semantically possible for a storage location of reference or pointer type to be accessed before code has been run to compute a value for it, there isn't any perfect choice as to what should happen. Having such locations default to null pointer references which may be freely read and copied, but which will fault if dereferenced or indexed, is one possible choice. Other choices include:

  1. Have locations default to a null pointer, but do not allow code to look at them (or even determine that they are null) without crashing. Possibly provide an explicit means of setting a pointer to null.
  2. Have locations default to a null pointer, and crash if an attempt is made to read one, but provide a non-crashing means of testing whether a pointer holds null. Also provide an explict means of setting a pointer to null.
  3. Have locations default to a pointer to some particular compiler-supplied default instance of the indicated type.
  4. Have locations default to a pointer to some particular program-supplied default instance of the indicated type.
  5. Have any null-pointer access (not just dereferencing operations) call some program-supplied routine to supply an instance.
  6. Design the language semantics such that collections of storage locations will not exist, except an an inaccessible compiler temporary, until such time as initialization routines have been run on all members (something like an array constructor would have to be supplied with either a default instance, a function that would return an instance, or possibly a pair of functions--one to return an instance and one that would be called on previously-constructed instances if an exception occurs during the construction of the array).

The last choice could have some appeal, especially if a language included both nullable and non-nullable types (one could call the special array constructors for any types, but one only be required to call them when creating arrays of non-nullable types), but would probably not have been feasible around the time null pointers were invented. Of the other choices, none seem more appealing than allowing null pointers to be copied but not dereferenced or indexed. Approach #4 might be convenient to have as an option, and should be fairly cheap to implement, but it should certainly not be the only option. Requiring that pointers must by default point to some particular valid object is far worse than having pointers default to a null value which can be read or copied but not dereferenced or indexed.

share|improve this answer

Yes, NULL is a terrible design, in object-oriented world. In a nutshell, NULL usage leads to:

  • ad-hoc error handling (instead of exceptions)
  • ambiguous semantic
  • slow instead of fast failing
  • computer thinking vs. object thinking
  • mutable and incomplete objects

Check this blog post for a detailed explanation: http://www.yegor256.com/2014/05/13/why-null-is-bad.html

share|improve this answer

I'm not reading every answer, nor do I know what your language of preference is.. but if it's a compiled language, then hell yes.. get rid of null pointers, because yes, it makes debugging much easier.

You wont always have control of what exactly causes runtime errors.. so minimize them when you compile, if for no other reason than to exclude them when the shit really does hit the fan.

share|improve this answer

Suppose you find this customer with as last name "Goodman", and you want to send him the goods, so you do:

if (paypal.getMoney(price, c.paypalAccount())) {
   product.deliverTo(c.address());
} else {
   noMoneyNoGoods();
}

A lot of things could go wrong: Perhaps the customer doesn't have a paypal account. Perhaps he doesn't have an address. Perhaps he HAS an address, but it's in a country where you're forbidden to export the product! Perhaps there's a division by zero somewhere, perhaps the database cannot be updated.

The only way to deal sanely with all these problems, is to use an exception system. Therefore since you already are wrapping this code with an exception handler, you can as well handle the CustomerNotFoundException.

Notice notably the case where the customer has an address, but you're forbidden to deliver the goods there. There's no null involved. Everything's perfectly in order.

This proves that the problem is not having null values, it's not having an exception system.

Finally, if you use a language that has no null pointer/reference/value, you can always instantiate an object and bind it to a variable named NIL, and use that (if the type system goes into your way, you may have to define several null values). Then you will again have either to test for this special value, or set up things to get an exception (e.g. those null values could be of a subclass where all methods are overloaded to signal an exception).

I hope I have convinced you that the idea that "the inclusion of null references in programming languages is the 'billion dollar mistake'" is wrong.

share|improve this answer
2  
Without null you'd find another way, and exceptions are not the only choice. Your nil object might be a choice in some cases, but the language shouldn't make that nil object be the default for every single type. –  Ricky Clarkson Aug 14 '12 at 19:43
1  
@Huperniketes How are exceptions terrible craftsmanship? If an error is usually handled several layers up the call stack, you'd have to unwrap and rethrow the Nothing element of Maybe/Option over and over again until you reach the handler. Moreover, when using high-order functions returning Maybe/Option may not be an option. –  Doval Mar 13 at 2:36

protected by gnat Aug 19 at 17:36

Thank you for your interest in this question. Because it has attracted low-quality answers, posting an answer now requires 10 reputation on this site.

Would you like to answer one of these unanswered questions instead?

Not the answer you're looking for? Browse other questions tagged or ask your own question.