
Deprecating: java.util.Optional.get()? - redcodenl
http://royvanrijn.com/blog/2016/04/deprecating-optional-get/
======
merb
actually 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...](http://www.scala-
lang.org/api/2.11.8/index.html#scala.Option@get:A)

~~~
masklinn
> 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
throwing a Exception would actually make the code as horrible as it already
was. You would either need a static method that transforms the exception into
a runtime exception or you would need a catch block that never occurs

~~~
masklinn
orElseThrow throws an unchecked exception.

------
nv-vn
Having 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.

~~~
neverminder
Java Optional was inspired by Scala Option was it not? And I haven't seen
anyone complain about Scala Option having exactly the same get() method for
ages.

~~~
haimez
It does, but the scala community is very familiar with the functional
("lambda") approach of leaving values in an optional context while
transforming it.

The issue here stems from the existing community's culture, one especially
full of trivially safe getters.

~~~
neverminder
Well, maybe they need to learn the lesson the hard way, because when they
start doing `foo.getBar().map(this::toString).orElse("Bar not found");` they
will realize (hopefully) that this looks much more like Scala than classic
Java.

------
breakingcups
So, 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
You'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.

------
willvarfar
The 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
The 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.

------
specialist
I 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.

~~~
lmm
Optional is like a generic NullObject. What should e.g. Map#get return, if not
Optional?

~~~
specialist
Java's Optional is exactly unlike a NullObject. Optional is not a Proxy. Being
untyped, not being an implementation of the interface, it can't be used
interchangeably.

It's NullObjects all the way down. Makes more sense when designs favor
compositions over inheritance.

Optional is the wrapper no one needed. For syntactic sugar, static library
methods worked just fine.

~~~
lmm
So once again, if you didn't have Optional, what should Map#get return?

~~~
specialist
Really?

    
    
      class Widget {...}
    
      class final NullWidget extends Widget {
        static NULL_WIDGET = new NullWidget();
        ...
      }
    
      class WidgetMap extends HashMap<String,Widget> {
        Widget get( String key ) { 
          if( contains( key )) { return super.get( key ); }
          return NULL_WIDGET;
        }
        ...
      }

~~~
lmm
Urgh. Sure that's one option, but I don't want to have to subclass HashMap
every time I want to store something different in it. Also sometimes I want
_generic_ code that uses a map.

~~~
cytzol
And sometimes you want a different type of map...

------
cesarb
So 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().)

~~~
cytzol
> 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.

------
makecheck
This 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.

~~~
mbizzle88
> 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));

------
strictfp
Why optimize for stupid usages of Optional?

------
raimille1
Love 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.

------
dudul
Not 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
> 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.

------
xer
What do they mean with "god forbid a microservice"?

~~~
acveilleux
Microservices 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
Yep! 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.

~~~
GrumpyYoungMan
Martin 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.

