No Null Beyond Method Scope

Problem

When catching a NullPointerException in Java the StackTrace? doesn't lead you to the real bug. It tells where a method call on a NullValue failed, but not where this NullValue came from. Tracking this down can take long debugger sessions - you lose hours or even days.

Solution

Never return null. Never accept null as parameter.

If NullValues exist only within method scope, you make sure that the creation of a NullValue and failing method calls are in the same method body. You don't need a debugger to get from the failed method call to the NullValue creation. Further more it's possible to avoid any NullPointerExceptions at all, since within a short of piece code like a method body one may keep track of NullValues avoid any method calls on them.

To check for null parameters UseAssertions or even better use AspectOrientedProgramming. In aspect oriented languages like AspectJavaLanguage? tests for null parameters and return values can be done in a very convenient way.

Instead of null as return value use the NullObject pattern, or if you can't do so throw a RuntimeException. If you throw an exception you should provide a possibility to check if the critical method can be executed without causing an exception. Hence..

try {
obj.get(foo);
}
catch (RuntimeException e) { ... }

..should be rewritten as..

if (obj.contains(foo)) {
// we are now sure that get(foo) doesn't throw an exception
obj.get(foo);
}

If this needs to be ThreadSafe you'll need to lock obj before contains() and release the lock after get()

If you can't avoid to return null choose a method name that makes this clear, e.g. getFooOrNull().

See also CheckDontCatch and DontCatchRuntimeExceptions.

I find that it is often better to have a parameter, such as 'bool IsRequired'. If the search/query method cannot find the object desired, then it checks IsRequired. If IsRequired is true, then the method throws an exception. If IsRequired is false, then the method returns null. This allows me to have a single method that can be used for the most common case (which, for my projects, has always been IsRequired == true), and yet still avoid the necessity to either query twice (contains, then query, which is extremely inefficient), or to require that an exception be thrown and caught, in a very common, expected case. -- ArlieDavis

Based on my experience you can save most of your debugging time when applying this idiom. -- AdrianKuhn?


This doesn't seem to be a problem to me. Sure, I get NullPointerExceptions in my code all the time, but they don't seem to be that difficult to track down. Since I try to observe LawOfDemeter, it's not too hard to figure out which value in a statement is the NullValue, and since I try to make sure my methods are never that long, it's not that hard to figure where the value is coming from.

I agree with this. I find that people do an awful lot of up-front checking for null values that needn't be done. I have never had a problem tracking down a NullPointerException. DontCatchRuntimeExceptions. -- IainLowe

In fact, NullPointerExceptions are the easiest bugs to resolve. The NoNullBeyondMethodScope approach, by hiding NullPointerExceptions, can make debugging more difficult. Still, for methods that return collections, it does seem more intuitive to return an empty collection instead of a NullPointer.

The NoNullBeyondMethodScope does NOT mean "hide null pointers", indeed, it means don't MAKE them and don't ACCEPT them. Not accepting them means throwing an exception at the earliest possible point that the null is discovered. -- JeffBay

NullPointerExceptions can be *very* difficult to solve in certain cases. If the system religiously observes the LawOfDemeter, it is not very common, however, even then they can be difficult to track down. The main problem children in the null pointer world are when a value is written to/ a setter is called from multiple places, and then the value is used in another place. There exist algorithms where the setters may be called from multiple locations is a common, desired and necessary structure. However, not preventing the assignment of null into the value means that the NullPointerException occurs at a point far away from the real error. In this case, you may spend endless hours playing "hunt the null pointer wumpus". -- JeffBay


You can get a lot of the benefit simply by applying the "don't return null" part. If you never return nulls, and convert what would be nulls into instances of the NullObject pattern, you shouldn't ever get them in. In addition, you code reads a lot nicer, because you don't have any "if (objectX == null) {...}" guff.

If you deal with APIs, the "don't accept nulls" should only go up at the entry interfaces. -- RobertWatkins

I don't agree that returning nulls is necessarily a bad idea, so long as you are following DesignByContract principles (whether your language formally supports DesignByContract or not). It is a question of the contract of the API. If the contract says that it returns null in such-and-such a condition, then it is the responsibility of the callers to deal with that return value. It should also be possible to pass nulls to arguments if the meaning of doing so is clearly defined in the contract. The issue here is really about communicating to the caller what their responsibilities are. Javadoc should be sufficient to define the contract in Java for this purpose, for example. -- BruceAtherton

I HaveThisPattern -- ChristianTaubman

See also SamuraiPrinciple.


I agree with Iain about needless up-front checking for null values - it's noise that detracts from the communication value of the code. Plus, if you use this idiom and you need to indicate to the caller of a querying method that the sought object isn't available, what do you do? Throw an exception? DontUseExceptionsForFlowControl. Use a ResultObject? Maybe, by why go to the trouble when you could DoTheSimplestThingThatCouldPossiblyWork by returning null. In my experience, most NullPointerExceptions are caused by uninitialized instance variables, which are corrected by applying well-known creation and initialization idioms, perhaps in combination with assertions, etc. I agree that if a method can return null its name or documentation should say so - but that's just normal communication. If a programmer of a client of that method assumes the return value is always non-null, shame on him. IMHO clear communication is the better way to reduce programmer error; not more code, which interferes with communication. -- RandyStafford

I'm with you on this Randy... if a function is always capable of returning a meaningful value, then it should, of course, never return null. If a function sometimes DOESN'T have a meaningful value to return, then you've got to do something. Throwing an exception makes sense sometimes, but not always. Returning a NullObject is a good idea if the code that uses this result can be simplified by that pattern. But if the code that uses this result simply needs to skip over the values that aren't meaningful, then we need a special NullObject with no methods or fields (or, in order to FailFast, which throws an exception whenever you try calling a method or accessing a field). This special NullObject is called "null". --MichaelChermside


I HaveThisPattern. I've used it to great success on a number of projects. The primary benefit is that null reference exceptions are particularly nasty to track down otherwise. Many applications I've seen will return null if passed a slightly out-of-bounds parameter, including null. Combine this with the habit of some applications to return null instead of throwing an exception, and you've got a situation in which the null exception stack trace is nowhere near the actual cause of the problem.

In my applications, returning null or passing in null is assumed to be an error except in specific situations. Every method would throw a null exception if one of its parameters was null. Fortunately, this wasn't as cumbersome as it sounds, because in Java, you get most null exceptions for free. Example:

 public void foo(Object a, Object b) {
   Assert.NotNull?(a);
   b.bar(a);
 }

We didn't have to assert b was not null because it was being dereferenced and we could count on Java throwing the exception for us. Having the Assert class helped too.

--JimShore

WRT Jim's comments, I'm not sure that relying on the runtime to throw NPE for you is a good idea, especially in class constructors. What happens if b.bar(a) is refactored into a class method that is called after the class constructor? Now you have a deferred NPE, which is exactly what this pattern is intended to avoid.

See this bug, for example: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4667036

--NiallSmart?

In the future, you might be able to let the compiler solve this problem for you in Java, like you can in some other languages. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5030232


The hidden problem here is that Java has no good mechanism for heterogeneous return types. Using a Null is, a problem for the reasons described above - it hides the error until the object is used. Using exceptions is, likewise, cumbersome because exceptions are slow and frequrent-exception-throwing makes debugging tedious. (ForgetTheDebugger might apply here) The problem is that sometimes the best solution is a "Cheap Exception" - like when doing hashtable access. You need some way to return "not found" to the caller... but using a null can result in error hiding, and using an exception is expensive and clumsy. When you think about it, exceptions _are_ the ideal mechanism except for their flaws... which is why languages need to stop treating exceptions as an afterthought.

Sometimes, the user needs to call a function that he expects could fail, because "LookBeforeYouLeap" is computationally wasteful. Any kind of remote behaviour (such as database calls) are chief examples of this - the "looking" part of "look before you leap" involves pointless network messaging, when it would be far more useful to say "try X, and if it doesn't work, describe the failure"... even if failure is an expected possibility (like an operation that can't be done if a collection on the remote server is empty). Null is a bad solution to this problem, because Null hides the failure, and can only model one failure mode. Python works well because it is designed for CoupleLookingWithLeaping?, with cheap, unencumbered exceptions.

For a time, I was considering how modern languages needed a construct similar to CeeLanguage's "Union" types, but with a type-safe type-switch-block to allow for handling heterogeneous returns... but once you get past the syntax, the semantics are nearly the same as exceptions. What we really want is a way to say "I expect the following exception. If it occurs, I don't want the debugger to halt, I don't want the stack-trace to be constructed, and I want it to happen as fast as possible". A "Catch Expected" statement, if you will. Of course, the "Catch Expected" block would make the function call more expensive than a conventional call if the call succeeds - but the caller needs to be able to make that tradeoff.

   interface Option<T> {
       T get() throws (UnsupportedOperationException);
       boolean isNone();
   }
   class Some<T> implements Option<T> {
       private final T it;
       Some(T it) {
            this.it = it;
       }
       T get() throws (UnsupportedOperationException) {
            return it;
       }
       boolean isNone() {
            return false;
       }
   }
   class None<T> implements Option<T> {
       None() { }
       T get() throws (UnsupportedOperationException) {
           throw UnsupportedOperationException;
       }
       boolean isNone() {
           return true;
       }
   }
You could, of course, add support for getOrElse and monadic chaining; this is just the basic example. Either<X, Y> should also be easy to implement.

In the interests of compatibility I'd advise using Guava's com.google.common.base.Optional rather than writing your own.


NeverIsNeverNever.


CategoryNull


EditText of this page (last edited January 3, 2014) or FindPage with title or text search