Why is null bad
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. Yes, NULL is a terrible design , in object-oriented world.
In a nutshell, NULL usage leads to:. Oftentimes you expect the result to be of a certain type. This is semantically sound. But, what if there is no user of that id? One bad solution is: adding a null value. So the result is ambigous : either it is a user or it is null. But null is not the expected type. And this is where the code smell begins. There are always ways around null : refactoring to collections, Null-objects , optionals etc.
Nulls are problematic because they must be explicitly checked for, yet the compiler is unable to warn you that you forgot to check for them. Only time-consuming static analysis can tell you that. Fortunately, there are several good alternatives. Take the variable out of scope.
Way too often, null is used as a place holder when a programmer declares a variable too early or keeps it around too long. The best approach is simply to get rid of the variable. Don't declare it until you have a valid value to put in there. This isn't as difficult a restriction as you might think, and it makes your code a lot cleaner. Use the null object pattern. Sometimes, a missing value is a valid state for your system. The null object pattern is a good solution here.
It avoids the need for constant explicit checks, but still allows you to represent a null state. It is not "papering over an error condition," as some people claim, because in this case a null state is a valid semantic state. That being said, you shouldn't use this pattern when a null state isn't a valid semantic state.
You should just take your variable out of scope. First of all, this lets the compiler warn you that you need to check for a missing value, but it does more than replace one type of explicit check with another. Using Options , you can chain your code, and carry on as if your value exists, not needing to actually check until the absolute last minute. In Scala, your example code would look something like:.
On the second line, where we're building the awesome message, we don't make an explicit check if the customer was found, and the beauty is we don't need to.
It's not until the very last line, which might be many lines later, or even in a different module, where we explicitly concern ourselves with what happens if the Option is None. Not only that, if we had forgotten to do it, it wouldn't have type checked. Even then, it's done in a very natural way, without an explicit if statement. Contrast that with a null , where it type checks just fine, but where you have to make an explicit check on every step of the way or your entire application blows up at runtime, if you're lucky during a use case your unit tests exercise.
It's just not worth the hassle. The central problem of NULL is that it makes system unreliable. In Tony Hoare in the paper dedicated to his Turing Award wrote:. And so, the best of my advice to the originators and designers of ADA has been ignored. Do not allow this language in its present state to be used in applications where reliability is critical, i.
The next rocket to go astray as a result of a programming language error may not be an exploratory space rocket on a harmless trip to Venus: It may be a nuclear warhead exploding over one of our own cities. An unreliable programming language generating unreliable programs constitutes a far greater risk to our environment and to our society than unsafe cars, toxic pesticides, or accidents at nuclear power stations. Be vigilant to reduce the risk, not to increase it.
ADA language has changed a lot since that, however such problems still exist in Java, C and many other popular languages. It is developer's duty to create contracts between a client and a supplier. The difference is significant. As a client of a method you know what to expect. A team can have the rule:. The team can strengthen this idea by using Design by Contract and static checking at compilation time, e.
These approach can drastically increase application reliability and software quality. Design by Contract is a case of Hoare logic , which was populated by Bertrand Meyer in his famous Object-Oriented Software Construction book and Eiffel language in , but it is not in use invalidly in modern software crafting.
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:. 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.
Basically the central idea is that null pointer reference issues should get caught at compile time instead of run time.
So if you are writing a function that takes some object and you don't want anyone to call it with null references then type system should allow you to specify that requirement so that compiler can use it to provide guarantee that call to your function would never compile if caller does not satisfy your requirement. This can be done in many ways, for example, decorating your types or using option types also called nullable types in some languages but obviously that's lot more work for compiler designers.
I think it is understandable why in s and 70s, compiler designer didn't go all-in to implement this idea because machines were limited in resources, compilers needed to be kept relatively simple and no one really knew how bad this would turn out 40 years down the line.
Sign up to join this community. The best answers are voted up and rise to the top. Stack Overflow for Teams — Collaborate and share knowledge with a private group. Create a free Team What is Teams? Learn more. Are null references really a bad thing? Ask Question. Asked 11 years ago. Active 2 years, 8 months ago.
Viewed 51k times. Improve this question. If only we could eliminate the source of all runtime errors, our code would be guaranteed to be perfect!
When Tony Hoare called null a billion dollar mistake, he was talking about language design. If you are designing a language, do it in a manner that does not allow null references. If your language already has null references, you have to kludge you way around them. Of the modern languages, I know Perl does not allow null references and I think Python and Ruby do not also. Unfortunately, Java does.
Show 5 more comments. Active Oldest Votes. Improve this answer. The main reason is that in. NET System. Nullable is limited to value types. After getting familiar with Haskell's Maybe , nulls start looking weird 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? 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.
Show 20 more comments. The easier it is to debug, the better. This answer is the same if applied to either of the OP's examples. Either you test for error conditions or you don't, and you either handle them gracefully or you don't. In other words, removing null references from the language doesn't change the classes of errors that you will experience, it will just subtly change the manifestation of those errors.
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. Might as well remove nulls and use a special type or pattern like a value type to indicate a meaningless value. 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. 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. Show 9 more comments. There are several problems with using null references in code. Third, null references introduces additional code paths to test.
I don't buy it, although I'm mostly stuck in statically typed land. Garbage data is so much rarer than null references, though. Particularly in managed languages. Points 4 and 5 are solid, but the NullObject is not a remedy. You will fall into even worse trap -- logic workflow errors. For example, if there's no navigationController in [self. Show 4 more comments. Since the proxy is responsible for generating the return result, it can guarantee that the result is always a non-null Optional.
In this use case, Optional becomes more like a baked in language feature. If the result of the proxied method is an instance of Empty, the user could simply call isEmpty to determine if it is empty or not. If the user wanted instead to use the kind of transforms in Optional, Empty could have another method test that returns an Optional. This gives the user the choice to just call isEmpty , or chain a call to test with a call to one of the Optional methods to transform the value as desired.
To me null is a great feature that should not be considered toxic. The toxic thing is how it is sometimes used badly by developpers. The NullContract type only hides a bug. Rather, before calling Find, there should be a call to a boolean method that verifies that the contract exists.
Only if it does, then Find can be used to retrieve it. When used this way, Find cannot be null. In your example returning Null is valid. This means the Find method found nothing. The bug is not properly handling the Find results. So you are basically arguing that even though we can use a proper Maybe type, then because some people will always use null then we should just give up and use it ourselves? I have a hard time agreeing with that logic. I halfway agree with Ben, although such a call can be problematic from a performance perspective.
One alternative is to just return a list, which would also be a valid data structure. After all something containing 0 or 1 results is still both a valid list, and locally acceptable as a list. Download the NDepend Trial and understand your. NET code base technical-debt within a few minutes. NDepend Improve your. NET code quality with NDepend. What Are the Alternatives? What should they be doing instead?
Throw an Exception In some situations in which people return null, the reasonable thing to do is to throw an exception. Null Object Pattern Consider the following lines of code:.
Find 42 ; contract. Extend 12 ;. I've heard some voices saying that checking for a returned null value from methods is bad design. I would like to hear some reasons for this.
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.
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. 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. Yes, returning NULL is a terrible design , in object-oriented world.
In a nutshell, NULL usage leads to:. More in my book Elegant Objects , Section 4. Checking for nulls is a common practice, even encouraged, otherwise you run the risk of NullReferenceExceptions everywhere. Its better to handle the error gracefully than throw exceptions when you don't need to. Its inventor says it is a billion dollar mistake! It depends on the language you're using. If you're in a language like C where the idiomatic way of indicating the lack of a value is to return null, then returning null is a good design if you don't have a value.
Alternatively, in languages such as Haskell which idiomatically use the Maybe monad for this case, then returning null would be a bad design if it were even possible. If you read all the answers it becomes clear the answer to this question depends on the kind of method. Firstly, when something exceptional happens IOproblem etc , logically exceptions are thrown.
When exactly something is exceptional is probably something for a different topic.. Untill we have an official way to denote that a function can or cannot return null, I try to have a naming convention to denote so. Just like you have the Try Something convention for methods that are expected to fail, I often name my methods Safe Something when the method returns a neutral result instead of null. I'm not fully ok with the name yet, but couldn't come up with anything better.
So I'm running with that for now. If the result of the method is something that would not have a good result in normal use, returning null is fine:. If there really should always be a non-null result, then it might be better to throw an exception:. If your function is intended to find an attribute associated with a given object, and that object does has no such attribute, it may be appropriate to return null.
If the object does not exist, throwing an exception may be more appropriate. If the function is meant to return a list of attributes, and there are none to return, returning an empty list makes sense - you're returning all zero attributes.
In a case like this it's meaningful to return null if the id doesn't correspond to an existing entity, as it allows you to distinguish the case where no match was found from a legitimate error.
People may think this is bad because it can be abused as a "special" return value that indicates an error condition, which is not so good, a bit like returning error codes from a function but confusing because the user has to check the return for null, instead of catching the appropriate exceptions, e.
Checking against NULL and not asserting for programmer errors or throwing for user or caller errors in the failure case can mean that later crashes are harder to track down, because the original odd case wasn't found.
Moreover, ignoring errors can lead to security exploits. Perhaps the null-ness came from the fact that a buffer was overwritten or the like. Now, you are not crashing, which means the exploiter has a chance to execute in your code. In this case we could: Return Null or throw a checked exception or maybe create an item and return it. I believe that return null may be less good than the alternatives becasue it requires the client to remember to check for null, programmers forget and code.
In Java, throwing a checked exception, RecordNotFoundException, allows the compiler to remind the client to deal with case. I find that searches returning empty lists can be quite convenient - just populate the display with all the contents of the list, oh it's empty, the code "just works".
Make them call another method after the fact to figure out if the previous call was null. Well, it sure depends of the purpose of the method Sometimes, a better choice would be to throw an exception.
It all depends from case to case. Sometimes, returning NULL is the right thing to do, but specifically when you're dealing with sequences of different sorts arrays, lists, strings, what-have-you it is probably better to return a zero-length sequence, as it leads to shorter and hopefully more understandable code, while not taking much more writing on API implementer's part.
The base idea behind this thread is to program defensively. That is, code against the unexpected. There is an array of different replies:. Adamski suggests looking at Null Object Pattern, with that reply being up voted for that suggestion. Michael Valenty also suggests a naming convention to tell the developer what may be expected.
And others. If we make the "rule" that we always want to do defensive programming then we can see that these suggestions are valid. Regardless of whether a class returns NULL for methods with a return value or not, the Developer will need to test if the object is valid. That is, if the "method call" to get the object does not do what it "advertises" eg getEmployee it has broken the contract. As an author of a class, I always want to be as kind and defensive and deterministic when creating a method.
ISVALID needs to be checked and that may need to happen with a collection of Employees, then the null object approach is the better approach.
An Author who throws an exception is removing the choice for the developer to test the object's validity, which is very bad on a collection of objects, and forces the developer into exception handling when branching their consuming code.
That is, a clearer intention of the method. Other approach would to to use exception to indicates failures, but here - there are actually many more voices, that say this is a BAD practice as using exceptions may be convenient but has many disadvantages. So I personally don't see anything bad in returning null as indication that something went wrong, and checking it later to actually know if you have succeeded or not.
Also, blindly thinking that your method will not return NULL, and then base your code on it, may lead to other, sometimes hard to find, errors although in most cases it will just crash your system : , as you will reference to 0x sooner or later.
Unintended null functions can arise during the development of a complex programs, and like dead code, such occurrences indicate serious flaws in program structures. A null function or method is often used as the default behavior of a revectorable function or overrideable method in an object framework.
If you have a dummy object whose execute method does nothing, and you return that instead of Null in the appropriate cases, you don't have to check for the Null case and can instead just do:. So, here the issue is not between checking for NULL vs. For my use case I needed to return a Map from method and then looking for a specific key. But if I return an empty Map, then it will lead to NullPointerException and then it wont be much different returning null instead of an empty Map. But from Java8 onward we could use Optional.
The above is the very reason Optional concept was introduced. Edit: This is true of languages where you don't have exceptions such as C where it has been the convention for many years. Stack Overflow for Teams — Collaborate and share knowledge with a private group. Create a free Team What is Teams? Collectives on Stack Overflow.
0コメント