Iris Classon
Iris Classon - In Love with Code

Stupid question 40: Should I return 'null' or throw an exception if a methods fails to produce requested value?

[To celebrate my first year of programming I will ask a ‘stupid’ questions daily on my blog for a year, to make sure I learn at least 365 new things during my second year as a developer]

Are you expecting a delivery or not?

This is very interesting as i had this discussion at work with a colleague just a couple of days ago, and Paul Blamire referred to that question in one of the comments on my previous post about how to return null from a generic method(give him a follow Twitter @pabloblamirez ). I started discussing this my colleague as I had a generic method that parsed json, the method would be mostly used in cases where I would expect it to produce a value- but not always. The ’not always’ (the method is a part of a helper class) made me decide on the return null, using default(T) (first I restricted it to classes, but realized that I wanted this method to return anything). Although fairly happy with my decision I think that this is a great question, and one worthy of a discussion!

My answer (and please do correct me if I am wrong!) is: (here is me talking to myself LOL )
I throw an exception if I am absolutely expect this to return a value, and handle it one way or another.
I return null if the method should be able to return null. If null would be considered an error, then I should have used an exception instead.

Any thoughts on this one?

EDIT:

I’ve gotten some great feedback on this one, and I’ve had a rethink about my approach. It makes more sense not to return null in dare I say most cases? Reading the arguments for and against I’ve come to the conclusion that for me it makes more sense not to return null, in most of the cases.

My new answer would be that I should write methods that are expected to return a value, and handle the exception if it fails to do so.

Quite a valuable lesson learned here for me, the biggest one so far from the ‘stupid’ questions. And maybe a valuable one for those reading this post, if you don’t ask and check whether your reasoning is right - even though you think the answer is given- you’ll never learn something new.

And yes, I did find my way to the StackOverflow question, here it is :D

Comments

Leave a comment below, or by email.
John MacIntyre
9/9/2012 3:39:39 AM
I'd say you nailed it with your " If null would be considered an error, then I should have used an exception instead." comment. 

Basically, you shouldn't be returning error codes. You should be throwing exceptions. 
Andrew
9/9/2012 3:15:05 AM
It depends on how important the return value is to your programme.
If the programme can continue, then I would return the null value, making
sure the user is aware of any lack of functionality due to the null value.

If the value of null hinders the functionality then produce the exception
and give the user clear instructions on how they can (if possible) rescue the situation. 
Scott Barnes
9/9/2012 2:59:15 AM
You could do return throw HTFDidYouDoThatException() 

:)

It depends on where it sits in the layer, if it's below the UI layer then i'd expect some hard returns as in the end testing for nulls can be a pain all the time especially when you assume or infer that a result would come back. That way you can also bubble the error higher up in the call stack to see if it was data being passed in that passed compile time & runtime checks but had semantic issues (ie business logic related). 
Troy Hunt
9/9/2012 3:56:36 AM
Beyond the very academic answers you'll probably get about exceptions being expensive (I say academic, because, well, exceptions should be an exception!) there's a fundamental semantic difference. An exception is almost always an indication of "Hey, something went wrong" whilst a null can well be an indication that everything ran just fine but there was simply no value to return. If you call into your data repository and the thing is offline, great, that's an exception. If you call into it and the desired item doesn't exist, a null result says "Everything worked, but I have nothing for you".

Just because you're absolutely positive a value should exist today, doesn't mean it will tomorrow. Then again, if you proceed with that exception then sooner or later you'll get an exception somewhere anyway! :) 
Martin D
9/9/2012 6:14:05 AM
In some cases, you might also use the Null Object Pattern (http://en.wikipedia.org/wiki/Null_Object_pattern) to handle a null. 

public interface Animal {
        void makeSound();
}
 
public class Dog implements Animal {
        public void makeSound() {
                Console.WriteLine("woof!");
        }
}
 
public class NullAnimal implements Animal {
        public void makeSound() {
        }
}
 
James Tryand
9/9/2012 6:34:49 AM
This problem boils down to the fact that your component/method/etc (ignoring side effects) can possibly return a number of different values, and might even fail for a number of different reasons (which might need to be handled differently), and that you are returning but a single value with the output state/outcomes being implicit in the result.

Personally I feel that nulls are bad to begin with as they essentially are an escape hatch from the type system, and a 'unit' or even empty value would almost invariably be a better choice but anyway.

I found that this problem is also related to one i've seen with an overuse of bools.
Essentially you are wanting two values to be returned : the value that you are interested in - such as the json string, new type etc. and a second value which informs you of the resultant state of the operation. 

The problem with the use of bool to denote resultant outcome is entirely that it is limited to two arbitrarily assigned values. it is possibly and reasonable to return a custom enum in this case to denote which of the possible outcomes it has been. ( or in the case of something like F# to use the more elegant option of discriminated unions ).

It might well be that an empty value of your given type is an appropriate response, and the outcome is implicit. 
The other option is to use exceptions; which can be provided in whatever flavors that you choose for them : and gives the rest of the system a fighting chance of knowing what the possible thing that happened that caused your method to return an empty value.

At the end of the day, the option is open to you to your choice, but by specifying the possible outcomes of your methods; it may take more time to reason about them, but from personal experience, every time I've done this, i've found that my code has been much more robust and i cannot recall having to go back and fix bugs in it, as by leaning on the type system, the compiler has taken care of those problems for me.

As an aside, you'll also notice that HTTP in it's own right works in this manner; having both the response and status code to denote the outcome of the operation requested upon it. 
Mike
9/9/2012 6:56:42 AM
A third option is to turn it into a TryX method that returns a bool and has an out parameter for the return result. This allows you to communicate the success/failure along with the result. Depending on the situation, null may be a valid result.

Is a failure something the calling code can handle? Is it something the calling code is expected to handle? The Try method signature helps communicate that this can fail and we expect you to handle that possibility. 
Matt Kerr (@kunikos)
9/9/2012 7:30:44 AM
Or you can write methods like, bool TryGetSomething(out something) where the return indicates failure and the out param is the result if it succeeded. The pattern is used elsewhere in the .NET Framework (TryParse).

Edit: Ahhh, Mike beat me. :( 
James Tryand
9/10/2012 5:49:05 AM
@mike @kunikos - sorry if mine was a bit tl;dr for you. it describes this approach and goes into more details as to why you may or may not want to use booleans as your status code. 
James Curran
9/11/2012 8:09:31 AM
I use both nulls and exceptions depending on the level of the problem.  Consider a method, Person.GetAge().   The obvious return value would be an int (or perhaps a decimal or TimeSpan), but they all assume that you have the information available.  But you may not have the person birthday.  Hence null would be appropriate for "I don't know".   On the other hand, if trying to get the value lead to a database connection error, that would get an exception. 
Mike
9/12/2012 6:00:59 PM
Reply to: James Tryand
@James Tyrand - I read your post after I had posted mine and you definitely covered it better. Unfortunately I wasn't fast enough to update my post like kunikos did. I especially like the idea of returning an enum result to communicate where things went wrong. 
Sarkie
10/10/2012 2:53:38 AM
No one mentioned "Maybe" Monad.

http://smellegantcode.wordpress.com/2008/12/11/the-maybe-monad-in-c/ 


Last modified on 2012-09-08

comments powered by Disqus