4 ms·
Not sure if satire. But if not: > Every NullPointerExceptipn my code ever caused was good, because it helped find an error state that had no acceptable default
by valenterry 5y ago
Not sure if satire. But if not:
> Every NullPointerExceptipn my code ever caused was good, because it helped find an error state that had no acceptable default non error state alternative.
Yeah, and with Optional you would have found it at compile-time.
- hashmash 5y agoOnly if you never have the case where Optional is empty but you expected it not to be. How often is Optional.get or orElseThrow called blindly? How often is boilerplate code written which checks if the optional is empty and then throws "should not happen" exception or just logs a message? Once NullPointerException got "helpful" messages, I don't see that much advantage to Optional, considering that it provides less information out of the box.
- convolvatron 5y agofor me this is one of the bigger festering wounds in programming. error handling doubles the size of the code. error handling is complicated. so we put on our big-dev pants and build all sorts of structures around handling errors to make it more sound/ergonomic. but at the end of the day: o its still very difficult to respond in a semantically meaningful way to errors as code o they still almost always just get dumped into a log or ignored, or just result in a panic o even if we have managed to surface them - they still aren't really that actionable by the end user so we haven't helped the situation much, but some of these answer like catch/throw have really unpleasant consequences - we may have made it worse
- valenterry 5y agoIt's pretty much a solved problem. Just use a language that has better ergonomics for errors. Scala's ZIO is one of the better examples if you are interested to look into an alternative.
- esrauch 5y ago> Only if you never have the case where Optional is empty but you expected it not to be I kind of think that sentence is contrary to the point of Optional, and if you start from that mindset then Optionals do end up no better than nulls. Instead you enforce good hygiene where you unwrap early and pass non-Optionals for anything that you "know" is non-null. If you call a function which returns optional, and you're find yourself thinking "nah, I _know_ this is definietly non-empty" then you're incorrect; the API explicitly is telling you that it definitely can be empty.
- hashmash 5y agoThere are certainly cases where Optional is better than a "this can be null" comment, but consider the possibility that the Map interface was designed to always return Optional. If I'm using a Map that I have complete control over, that I know what's in it (I think), then I'll call Map.get(x).orElseThrow(). This isn't an improvement over a Map.get(x) call that can return null. It's also uglier, and as shown by the Rust benchmark, much slower. I'd be happier with a Map interface that had a "tryGet" and "get" pair, where only the latter threw an exception. No need for Optional.
- valenterry 5y agoIt _is_ an improvement. If you just do "Map.get(x)" and you get null because your thinking was wrong, then the NPE will pop up potentially 10 layers later or an hour later, when the null-value was tried to be used in your program. On the other hand, with "Map.get(x).orElseThrow()" you will have an exception thrown immediately! Even better, you should customize that as "Map.get(x).orElseThrow(NoSuchElementException(x))" so that you know the value that was unexpectedly not in the list. That will make debugging much easier and will potentially fail a test case while a "Map.get(x)" might not cause the test to fail.
- thinkharderdev 5y agoThe advantage is if you are explicitly modelling a value that could be empty. You can encode that into the type system by making git an Option<T> instead of just a T (that could be null). At it's most basic level it can just help reduce the possibility of NullPointerExceptions but the real benefit and reduction of boilerplate comes when you use Option as a monad. For instance, in Scala if you have a something like case class Address(street: String, city: String, state, String) case class User(id: Int, name: String, address: Option[Address]) def filterCAUsers(users: List[User]): List[User] = users.filter(_.address.exists(_.state != "CA"))
- shawnz 5y agoUsing "Optional" doesn't provide any extra compile-time guarantees except that the function could return Optional.empty(). It's already possible to see that it could return null, so there's no extra guarantees there. The only advantage of "Optional" is that it lets you deal with the empty/null case with a nice functional API instead of if statements. It doesn't do anything to solve the reverse problem of guaranteeing that non-Optional functions can't return null. If you just want to provide a hint to the caller at compile time about whether you intend for the possibility of returning null, you could use @Nullable/@NotNull annotations to achieve that with no overhead.
- ubercow13 5y agoYes, in a language like Java where it's retrofitted in years after the decision was already made to allow literally everything to be null. In other languages, that doesn't apply.
- brabel 5y agoIt doesn't apply in other languages either as long as their nulls are "safe", as in Kotlin or TypeScript.
- Zababa 5y agoThe thing is that people usually don't have a lot of code to handle the null case, so having optional where you can easily chain the happy case often offers a better experience. It also allows you to differentiate when people will return null for nothing, or when they will return an empty object. I know that in the codebase I work with, people use both. With Optional, you don't have that problem.
- shawnz 5y agoWhy not just chain the happy case by ignoring nulls, and let any potential NullPointerException bubble up to the point in the code where you would have had an "Optional.orElse" or whatever? Isn't that often just as easy? If you want it to be explicit then you could just add "@throws NullPointerException" to your javadoc. And of course having Optional in your type signature doesn't guarantee you'll never return empty objects (or even null).