StackOverflow has a good discussion about this exact topic in this Q&A. In the top rated question, kronoz notes:
Returning null is usually the best idea if you intend to indicate that no data is available.
An empty object implies data has been returned, whereas returning null clearly indicates that nothing has been returned.
Additionally, returning a null will result in a null exception if you attempt to access members in the object, which can be useful for highlighting buggy code - attempting to access a member of nothing makes no sense. Accessing members of an empty object will not fail meaning bugs can go undiscovered.
Personally, I like to return empty strings for functions that return strings to minimize the amount of error handling that needs to be put in place. However, you'll need to make sure that the group that your working with will follow the same convention - otherwise the benefits of this decision won't be achieved.
However, as the poster in the SO answer noted, nulls should probably be returned if an object is expected so that there is no doubt about whether data is being returned.
In the end, there's no single best way of doing things. Building a team consensus will ultimately drive your team's best practices.
Answer from JW8 on Stack ExchangeStackOverflow has a good discussion about this exact topic in this Q&A. In the top rated question, kronoz notes:
Returning null is usually the best idea if you intend to indicate that no data is available.
An empty object implies data has been returned, whereas returning null clearly indicates that nothing has been returned.
Additionally, returning a null will result in a null exception if you attempt to access members in the object, which can be useful for highlighting buggy code - attempting to access a member of nothing makes no sense. Accessing members of an empty object will not fail meaning bugs can go undiscovered.
Personally, I like to return empty strings for functions that return strings to minimize the amount of error handling that needs to be put in place. However, you'll need to make sure that the group that your working with will follow the same convention - otherwise the benefits of this decision won't be achieved.
However, as the poster in the SO answer noted, nulls should probably be returned if an object is expected so that there is no doubt about whether data is being returned.
In the end, there's no single best way of doing things. Building a team consensus will ultimately drive your team's best practices.
In all the code I write, I avoid returning null from a function. I read that in Clean Code.
The problem with using null is that the person using the interface doesn't know if null is a possible outcome, and whether they have to check for it, because there's no not null reference type.
In F# you can return an option type, which can be some(Person) or none, so it's obvious to the caller that they have to check.
The analogous C# (anti-)pattern is the Try... method:
public bool TryFindPerson(int personId, out Person result);
Now I know people have said they hate the Try... pattern because having an output parameter breaks the ideas of a pure function, but it's really no different than:
class FindResult<T>
{
public FindResult(bool found, T result)
{
this.Found = found;
this.Result = result;
}
public bool Found { get; private set; }
// Only valid if Found is true
public T Result { get; private set;
}
public FindResult<Person> FindPerson(int personId);
...and to be honest you can assume that every .NET programmer knows about the Try... pattern because it's used internally by the .NET framework. That means they don't have to read the documentation to understand what it does, which is more important to me than sticking to some purist's view of functions (understanding that result is an out parameter, not a ref parameter).
So I'd go with TryFindPerson because you seem to indicate it's perfectly normal to be unable to find it.
If, on the other hand, there's no logical reason that the caller would ever provide a personId that didn't exist, I would probably do this:
public Person GetPerson(int personId);
...and then I'd throw an exception if it was invalid. The Get... prefix implies that the caller knows it should succeed.
The rationale behind not returning null is that you do not have to check for it and hence your code does not need to follow a different path based on the return value. You might want to check out the Null Object Pattern which provides more information on this.
For example, if I were to define a method in Java that returned a Collection I would typically prefer to return an empty collection (i.e. Collections.emptyList()) rather than null as it means my client code is cleaner; e.g.
Collection<? extends Item> c = getItems(); // Will never return null.
for (Item item : c) { // Will not enter the loop if c is empty.
// Process item.
}
... which is cleaner than:
Collection<? extends Item> c = getItems(); // Could potentially return null.
// Two possible code paths now so harder to test.
if (c != null) {
for (Item item : c) {
// Process item.
}
}
Here's the reason.
In Clean Code by Robert Martin he writes that returning null is bad design when you can instead return, say, empty array. Since expected result is an array, why not? It'll enable you to iterate over result without any extra conditions. If it's an integer, maybe 0 will suffice, if it's a hash, empty hash. etc.
The premise is to not force calling code to immediately handle issues. Calling code may not want to concern itself with them. That's also why in many cases exceptions is better than nil.
I am a learning java, btw why is used the return null;?
int is a primitive, null is not a value that it can take on. You could change the method return type to return java.lang.Integer and then you can return null, and existing code that returns int will get autoboxed.
Nulls are assigned only to reference types, it means the reference doesn't point to anything. Primitives are not reference types, they are values, so they are never set to null.
Using the object wrapper java.lang.Integer as the return value means you are passing back an Object and the object reference can be null.
Change your return type to java.lang.Integer . This way you can safely return null
The dilemma
If a variable with null value gets used in your program causing a NullPointerException, this is clearly a situation in your program which you did not expect. You must ask yourself the question: "Did I not expect it because I didn't take into consideration the possibility of a null value or did I assume the value could never be null here?"
If the answer is the latter, the problem isn't because you didn't handle the null value. The problem happened earlier, and you're only seeing the consequence of that error on the particular line it's used. In this case, simply adding a if (variable != null) isn't going to cut it. You'll wind up skipping lines you were supposed to execute because the variable was null, and you'll ultimately hit a line further on where you again assumed it wouldn't be null.
When null should be used
As a general rule, return null only when "absent" is a possible return value. In other words, your data layer may search for a record with a specific id. If that record isn't found, you can either throw an exception or simply return null. You may do either, but I prefer not to throw exceptions in situations where the strong possibility exists. So you return null instead of a value.
The caller of this method, presumably written by you, knows the possibility exists that the record may not exist and checks for null accordingly. There is nothing wrong with this in this case, though you should handle this possibility as soon as possible as otherwise everywhere in your program you will need to deal with the possibility of a null value.
Conclusion
In other words, treat null as a legitimate value, but deal with it immediately rather than wait. Ideally in your program, you should ever only have to check if it is null once in your program and only in the place where such a null value is handled.
For every value you expect to be non-null, you need not add a check. If it is null, accept that there is an error in your program when it was instantiated. In essence, favor fail fast over fail safe.
Deciding whether or not null is a allowed as an object value is a decision that you must make consciously for your project.
You don't have to accept a language construct just because it exists; in fact, it is often better to enforce a strict rule against any nullvalues in the entire project. If you do this, you don't need checks; if a NullPointerException ever happens, that automatically means that there is a defect in your code, and it doesn't matter whether this is signalled by a NPE or by some other sanity check mechanism.
If you can't do this, for instance because you have to interoperate with other libraries that allow null, then you do have to check for it. Even then it makes sense to keep the areas of code where null is possible small if possible. The larger the project, the more sense it makes to define an entire "anti-corruption layer" with the only purpose of preserving stricter value guarantees than is possible elsewhere.
I’m planning on delivering a tech talk to my team on the pitfalls of explicitly returning nulls in production code, as opposed to using optionals where the language supports it or throwing exceptions when the value is expected to be present.
To make sure I’m not presenting an overly biased view, and to avoid getting blind-sided if someone raises a point I hadn’t considered, I want to hear examples of times you would actually prefer to explicitly return null.
Edit: Since some were curious and I neglected to specify, our team works predominantly in Java so we do have the Optional interface available to us. I have also worked with Go a bit and tbf I did like the ability to have multiple return values in the case of errors etc. I also don’t mind how Swift/Kotlin handle optionals and unwrapping them, I believe they handle it in a similar way.