All. I am reading a book called and one of the idea is "Don't return null" when writing a method. He suggests either "throw out exception" or "use special case" when the function has to return null.
If the method return type is a list, I know I can return a empty list instead of null. However, what if the return type is a specific object. For example, a method to search database by unique id and return the result. What should I return if the method can not find anything?
I tried to use "throw out exception" but end up writing more coded and additional logic for any place calls the function.
Any suggestion will be appreciated.
Throwing an exception is an expensive operation, since there is a context switch and a lot of debug information has to be gathered, so you want to avoid throwing them as a way to control process flow (especially if you can handle the situation without throwing exceptions). Returning a null can be perfectly acceptable in order to avoid catching exceptions.
An example of this in action would be a couple of LINQ functions in C#. These methods can return a null:
SingleOrDefault(); // returns a single instance of an object, or null if not found
FirstOrDefault(); // returns the first matching object, or null if not found
This allows you to check for null without trying to figure out control flow using exception handling.
One exception (pardon the pun) that I can think of is using exceptions to communicate across program boundries. If you had, for example, a data access layer in a separate DLL, and you needed to communicate a database failure back to the parent program, sometimes the best way to do that is through exception handling.
If you don't want to return null, then you could use something like an Optional class.
Null is defined as non-existence, which seems to fit in perfectly with what you want. If your code returns nothing return nothing, right?
BUT, as always, it depends.
If your code is not meant to return nothing then doing so can cause untold problems. In this case it's definitely better to throw an exception. 1 / null
, won't work everywhere.
If non-existence is a perfectly valid return value then why would you want to return an exception? Assuming of course that you've got the code in place to deal with a non-existent value being returned from your query then there's no need to throw an exception at all.
If Null
might be a possible value you could return, then you should not return Null
if you cannot find anything. For example, in:
[1, 2, 3, Null, 5].find(nonInteger) -> Null
[1, 2, 3, 4].find(nonInteger) -> Null
the .find
function cannot return Null
to indicate failure, because sometimes it would return Null
on success! Instead, you can either change the semantics, or use a special object:
# changed semantics (with extra information returned)
[1, 2, 3, Null, 5].find(nonInteger) -> index=4, value=Null
[1, 2, 3, 4].find(nonInteger) -> index=Null, value=Null
# changed semantics (with wrapper)
[1, 2, 3, Null, 5].find(nonInteger) -> new Maybe(Null)
[1, 2, 3, 4].find(nonInteger) -> new Maybe()
# special object
NoResultFound = new object()
[1, 2, 3, Null, 5].find(nonInteger) -> Null
[1, 2, 3, 4].find(nonInteger) -> NoResultFound
I don't see any problem with returning null, but throwing an exception seems like the most sensible alternative. Your best bet would be to create your own, custom Exception class.
The code should look just about the same either way:
try {
SearchResult someResult = searchForStuff();
}
catch ( ResultNotFoundException rnfe ) {
/* do stuff */
}
/* almost the same as this */
SearchResult someResult = searchForStuff();
if ( someResult == null ) {
/* do stuff */
}