Thursday, September 8, 2016

Java 8's Optional

That's Optional

Discussions about Java 8's class Optional are popping up a lot lately around the office. It turns out that java.util.Optional has generated a lot of discussion by a lot of people. The root node seems to be a Stack Overflow post by Brian Goetz. He is in as good a position as anyone to know Optional's back story.

...But we did have a clear intention when adding this feature, and it was not to be a general purpose Maybe or Some type, as much as many people would have liked us to do so. Our intention was to provide a limited mechanism for library method return types where there needed to be a clear way to represent "no result", and using null for such was overwhelmingly likely to cause errors.

Wait. What?

  Our intention was to provide a limited mechanism for library method return types.
I'm not sure what that means. Is a library method a method that ships with the Java Runtime Environment? Is Spring Boot a library? Is a JAR a library? And why is the mechanism limited? In what ways it is intended to be limited?

What are others saying

How I Almost Used Optional. Twice!

I have submitted two pull requests that used Optional instead of null checks. The pull requests were a month or two apart, so I had time to think about it between each time.

In both cases, the code was peer-reviewed and peer-review lead to long comment chains about Optional. In both cases I ended up ripping out Optional and submitting pull requests with null and null checks.

The code base is imperative, and null checks are the province of imperative programming. Optional is a monad, and monads are the province functional programming. The two do not mix well.

When Java 5 if statements and for-each loops sit next to Java 8 monads and lambdas, you get cognitive dissonance.

TL;DR - Do Not Mix Imperative and Functional Styles

Sleek skyscrapers and gothic churches each have a place in the world, but that does not mean they should exist side-by-side.

Nothing is wrong with the pieces,
but something is not right with the whole.

Mixing monads and lambdas with traditional imperative code creates something surreal that is hard to read and is ultimately dissatisfying. Just because Java lets you mix programming paradigms, does not mean you should.

Pick a paradigm and stick to it. At least within a package. My advice is based on very limited experience, but it feels like packages should be either imperative or functional. It's fine for imperative and functional packages to interact. But within the package, there really needs to be a single programming paradigm. Right, Chava?


And a Lisp Shall Show Them The Way

Hungry for another way? Check out:
How do they address some of the same problems as Java's Optional? Do you find nil punning and destructuring more or less appealing than null checks? How about monad's like Optional?