7 ms·
Deprecating: java.util.Optional.get()?
- makecheck 10y agoThis kind of thing is so frustrating because enormous effort has been put into solving exactly one VARIANT of a pretty general problem. The general case is: at a particular point in the code, is $THIS_DATA usable or not, for some appropriate definition of “usable” in that code? And if “usable” has any additional meaning besides “is not null”, this entire machinery is useless because one STILL has to figure out the state of the data! For example, what if you are sanitizing input from a user and there is a “wall” in your code beyond which a string is considered safe (e.g. decoded, evaluated by regex, or whatever is supposed to happen)? Or, what if “usable” means that a server has been connected to, or a database opened, or a calculation completed, or whatever else you want to say? What if it’s a numerical denominator and you want it to be nonzero? The list could go on and on, and none of these architectures deals with ANY of those possibilities.
- winstonewert 10y agoWhat entire machinery? Optional is just one very simple class. And classes like Optional have long existed to solve most of the issues you bring up, see Gwt's SafeHtml, Futures, etc.
- mbizzle88 10y ago> And if “usable” has any additional meaning besides “is not null”, this entire machinery is useless because one STILL has to figure out the state of the data! That's inaccurate. In fact Optional makes this situation (having to check if data is not null and valid) even easier, because you can simply filter/map the value without having to first check that it is non-null. For example: possibleResult.filter(res -> isValid(res)) .ifPresent(res -> doSomething(res));
- breakingcups 10y agoSo, can anyone explain to me how this: Database.readOrder() .map(OrderEngine::process) .filter(ProcessResult::succeeded) .ifPresent(Database::storeResult); Is more readable than the supposed "unpleasant old skool": Order order = Database.readOrder(); //can be null if(order != null) { ProcessResult result = OrderEngine.process(order); if(result != null && result.succeeded()) { Database.storeResult(result); } } Maybe I'm "old skool" but I find the second much easier to read than the first.
- cytzol 10y agoYou're right, actually -- it's not more readable. Java developers already understand nulls, comparisons, and if statements. However, the second version is a lot more brittle than the first. It's relatively easy to change the code and still get it to compile, whereas you'll have a lot more trouble doing that with the first. For example: 1. If you forget to check 'order' for null, it'll still compile fine, because null is a valid value for type 'Order'. But if you try to feed an Optional<Order> to OrderEngine, it won't compile. 2. If you forget to check 'result' for null, it'll still compile fine, and then throw an NPE when you run 'result.succeeded()'. Again, if you try to call check ProcessResult::succeeded in the first example, it won't compile unless you deal with the empty-result case specifically. 3. Say that later on you want to get your stored values back out of the database... and you find a null in there. Where did it come from? If you forget to check 'result' for null and don't do the 'succeeded()' check, you can put a null in the database. Then your program will work fine until you try to call a method on it, at which point it throws an NPE far, far away from the point where you store it. By using Optional and dealing with the empty case, your code won't compile if you try to store null in the DB. So unfortunately it will be less readable until Java devs adjust themselves to using this new type, but the benefits do exist.
- reitanqild 10y agoI agree but admit it might be down to my lack of experience with functional programming. Background: many moons ago when I was still in school and VB was a valid choice of programming language I thought I new object oriented programming since my VB skills was decent (for a student) and VB had objects. I have learned a lot since then and suspect something similar is happening and will happily admit that good stuff can be waiting for me as soon as it "clicks" when I get time to sit down with it or get a colleague who knows it and explain it (or when someone on HN gives me a good explanation : )
- xer 10y agoWhat do they mean with "god forbid a microservice"?
- acveilleux 10y agoMicroservices are often basically equivalent with RPC calls. So they have a lot of potential failure modes like service down, network partitioned, timeout, etc. So each of them has a potential for an unexpected and transient failure that may be returned either via an exception or via a null result. In my own experience with systems built on top of multiple services (not micro in my case but enough services...) unexpected nulls or incorrectly handled exceptions from transient/network failures in the services depended on is a common mechanism that surfaces bugs in production code. And these bugs rarely show up in testing unless someone went out of their way to simulate the failure(s). Optionals have been a good way for us to convey that possibility to the calling code and force the consumer to consider the possibility and plan an appropriate response (we're big fans of fail-fast).
- exabrial 10y agoYep! It's the fallout from people that didn't learn the lessons in the great SOA/ESB era :P I can't remember who said this originally, but it was something like "The first rule of distributing your application is don't." The implication is you should distribute by business concern, not by tech concern.... which could be done with microservices, but it's not how they're being used right now.
- acveilleux 10y agoYeah and before the SOA/ESB folks, it was CORBA/DCOM (and but uttering those words, I am now too old to be marketable.)
- GrumpyYoungMan 10y agoMartin Fowler's First Law of Distributed Object Design: Don’t distribute your objects! http://www.drdobbs.com/errant-architectures/184414966 http://www.drdobbs.com/errant-architectures/184414966 Just skimmed through the article and found myself nodding all the way through.
- nv-vn 10y agoHaving the get() method makes the entire purpose of Optional useless. All it does is make your null-checking code even more verbose. If you need to extract the value, the orElse method should be suitable on all cases. Deprecating get() should be an instant decision, since other than backwards compatibility it has nothing to add to the Optional class. Including it in the first place was as much of a mistake as the null pointer.
- noamsml 10y agoI disagree. I'd rather getWhenPresent than orElse if the code has nothing to do with a missing value. If someone needs the value and uses orElse without isPresent, their code will break in new and unexpected ways rather than in the obvious one. (An even better solution is SWIFT's approach to nullable types, but that boat has sailed; intellij etc could however implement a static checker for bare Optional-getting)
- redcodenl 10y agoHow does orElse() cause new problems and/or break code? It is the same as get but forces you to think about the not available option...? I think the options orElse/orElseGet and orElseThrow are enough to replace every get() method, and they'll force you to think about the missing scenario. If you want to do something in case it is present, use ifPresent(lambda). In case you want to return something, use orElse/orElseGet or orElseThrow, or just return the Optional itself.
- masklinn 10y ago> I think the options orElse/orElseGet and orElseThrow are enough to replace every get() method, and they'll force you to think about the missing scenario. orElseThrow doesn't force you to think about the missing scenario, only to think about which exception you want to throw, which in many case you don't care for. If orElseThrow had an override throwing NoSuchElementException by default it would be a perfect replacement, alas it does not.
- 10y ago
- willvarfar 10y agoThe name getWhenPresent() doesn't seem descriptive to me. There is already orElse(value) and orElseThrow(exception), so why not add a plain orElseThrow() to raise the default exception?
- redcodenl 10y agoThe existing methods orElse(defaultValue) and orElseGet(supplier) and orElseThrow(exception) should be enough to cover everything get() does. But the Java community should move towards ifPresent/map/filter/flatMap etc.
- dudul 10y agoNot sure `getWhenPresent()` is better. Maybe `unsafeGet()`? That's a pattern found a lot on functional structures such as `IO` or `Task`. There could be a discussion to remove `get` altogether, but I don't think it would be a good idea. I don't use the Java type, but `scala.Option` and I think `get` is occasionally helpful in unit tests, scripts, etc.
- masklinn 10y ago> Not sure `getWhenPresent()` is better. Maybe `unsafeGet()`? That's a pattern found a lot on functional structures such as `IO` or `Task`. It's not unsafe, it safely throws an error when the optional is empty. There already is a #orElseThrow(Exception), there could be a #orElseThrow() defaulting to raising NoSuchElementException.
- specialist 10y agoI will never use Java's Optional. I'm baffled why it even exists. Further, I remain unclear on the value (haha) of the @Nullable and @NotNull annotations. If it's not baked into the language, why bother? I've been using NullObject since (checking...) 1996. This is The Correct Answer. http://c2.com/cgi/wiki?NullObject http://c2.com/cgi/wiki?NullObject I first read about NullObject here: Object-Oriented Design Heuristics http://amzn.to/1ND1YSU http://amzn.to/1ND1YSU What'd be really neat is some mojo to remove the boilerplate of implementing NullObjects.
- pron 10y ago> I remain unclear on the value (haha) of the @Nullable and @NotNull annotations. If it's not baked into the language, why bother? What's the difference between "baked into the language" and a language with built-in support (added in Java 8) for pluggable, inferrable type systems (of which @NotNull is just one, pretty basic, example)?
- specialist 10y agoIn principle and practice, I oppose all use of annotations. It's metaprogramming (aka magic). Being the new COBOL, Java is best when it just works. Anyone who can use annotations responsibly will be happier choosing a grown up language like Clojure. In truth, I don't have an answer for why method?method?property syntax is better than using annotations. Because I tend to use NullObjects and avoid method chaining, to me it's a false choice. Edit: Concision.
- pron 10y ago> I oppose all use of annotations. It's metaprogramming (aka magic). Don't conflate annotations (a compile time construct) with how they can be used. They can be used in many ways. When used as runtime metadata they can be "magic". But @Nullable/@NonNull is (or rather, can be used as) one of Java 8's pluggable type systems, inferred and and checked at compile time[1]. [1]: http://types.cs.washington.edu/checker-framework/current/checker-framework-manual.html#nullness-checker http://types.cs.washington.edu/checker-framework/current/che...
- merb 10y agoactually that would be a bad idea. considering you want to handle multiple options at once. the code would get really messy with flatMap/map another way would be (now consider more options and it will be way more ugly or considering a list of optional where every optional needs to be present to calculate something): if (opt1.isPresent() && opt2.isPresent() && opt3.isPresent()) { int i1 = opt1.get(); int i2 = opt2.get(); int i3 = opt3.get(); } of course scala has a better way of handling that: for (i1 <- opt1; i2 <- opt2; i3 <- opt3) yield (i1, i2, i3) But java has no support for generators. Edit: btw. even Scala has `get()` and it was there a long time even when you need it even less there: http://www.scala-lang.org/api/2.11.8/index.html#scala.Option@get:A http://www.scala-lang.org/api/2.11.8/index.html#scala.Option...
- lmm 10y agoScala has grown organically and has a lot of things that are no longer idiomatic. Wartremover makes Option#get a compile error, and many recommend using it on new codebases.
- merb 10y agostill on java you don't have for generators so it will be really messy to have a big nested flatMap block.
- deleted 10y ago[deleted]
- masklinn 10y ago> actually that would be a bad idea. considering you want to handle multiple options at once. The proposal is to rename the method[0], not to remove it entirely. So the code you're showing would still be possible, only clearer that it's not innocuous (the body relies very very strongly on the conditional) [0] not sure why adding an override to #orElseThrow to throw a default exception is not on the table
- merb 10y ago
- cesarb 10y agoSo Optional.get() is similar to Rust's Option.unwrap(), right? A method with a short name, which newbies often use just more than they should, and which should only be used when it's a bug if the Optional/Option doesn't contain a valid value at that point? (I still don't quite get the point of Optional; you're replacing a direct pointer with a pointer to a pointer, but the outermost pointer can still be null, so you are still vulnerable to a NullPointerException, and now you have two "not present" values to check for: null and !isPresent().)
- lmm 10y agoIt provides a migration path that allows deprecating null entirely. The next step is to deprecate methods like Map#get in favour of versions that return Optionals, ultimately arriving at a language where null can never happen when doing non-deprecated things. It's a multi-decade project but I don't see any other way to get rid of null while maintaining Java backward compatibility.
- hepta 10y agoThe point (or the reason why I use it) is to express the possibility of absent values, same as Rust, Haskell, etc. That the language let's you have null references is another (bigger) problem.
- Sharlin 10y agoSure, to be sure the type system needs to support non-nullable references. However, even without those, proper use of Optionals means getting a null result becomes an assertable bug in all cases, not a potentially valid code path signalling "not available" that should be checked.
- cytzol 10y ago> the outermost pointer can still be null, so you are still vulnerable to a NullPointerException This is true, but there is a distinction: if your Optional value is null, for any reason, then it's a programming error and should be fixed. If a non-Optional value is null, there's no telling whether it's "allowed" to be null or not. So I never null-check my Optionals in Java -- I'd rather they fail so I can be alerted to them.
- raimille1 10y agoLove it!! As a Java 7 developer transitioning to Streams this made no sense to me and ended up doing the optional.isPresent() -> optional.get() ... Took me to learn a pure functional language (Scala) to come back and start using map, filter, etc ... Not because Java 8 doesn't support it, but because a functional language community just has that mindset. There are many Java 8 developers using streams() and optionals with an imperative programming mindset still.
- strictfp 10y agoWhy optimize for stupid usages of Optional?