Avoid Optional Fields or Parameters

 class​ Communicator {
 
» Optional<Connection> connectionToEarth;
 
»void​ setConnectionToEarth(Optional<Connection> connectionToEarth) {
 this​.connectionToEarth = connectionToEarth;
  }
» Optional<Connection> getConnectionToEarth() {
 return​ connectionToEarth;
  }
 }

In Favor Optional Over Null, you’ve seen that you should rather return Optional values instead of null references. When people learn about Optional, they start to apply it everywhere and for everything. Don’t make this mistake! There are situations where Optional can make your code more complicated and inconvenient to use. So let’s go over where you should avoid it.

In the code above, we have an Optional field with a setter and getter. From the outside, the code looks nearly identical to the solution in Favor Optional Over Null. The getter returns an Optional<Connection>. This makes it explicit that the Connection can be absent.

The problem is that the field, connectionToEarth, itself is typed as optional. And there’s also a setter that accepts an Optional<Connection>. This introduces more problems than it solves. Can you think why?

We know that an Optional has two states: it’s absent (or Optional.empty()) or present. Those states make sense. But if you have an optional field or method parameter, then this variable can be null as well. So suddenly you have three states: present, absent, or null. What’s it supposed to mean if an Optional is null from a semantic point of view? Is it even more absent? That doesn’t really make sense. Maybe null in this case means that the current connection should be reset? This isn’t clear from the code.

Using optional for typing fields or parameters just makes everything more complicated. We can set fields to null and pass null to methods even with Optional fields or parameters. If you use them, you’ll have to check not only for null values, but also whether a value is present.

So what should you do if you encounter Optional fields or parameters?

 class​ Communicator {
 
» Connection connectionToEarth;
 
 void​ setConnectionToEarth(Connection connectionToEarth) {
 this​.connectionToEarth = Objects.requireNonNull(connectionToEarth);
  }
» Optional<Connection> getConnectionToEarth() {
»return​ Optional.ofNullable(connectionToEarth);
  }
 
 void​ reset() {
» connectionToEarth = ​null​;
  }
 }

It’s relatively straightforward: you should remove the Optional part in the types of fields and method parameters. You should keep the Optional types only as return values. This removes the semantic overload between Optional.empty() and null values.

But if you look at the code above, you can see that it’s not as simple as changing types only. When we remove the Optional type of the setter’s method parameter, we need to deal with the fact that you can insert null. That was conveniently ignored in the code before. In this case, we check for null values through the useful API method Objects.requireNonNull().

We’ve also added an additional method, reset(), which gives meaning to a null as prior input parameter. With the reset() method, it’s now possible to break the current connection without having to insert an explicit null into the setter. This is more robust and, as you may already have noticed, an application of Split Method with Optional Parameters. All usages of null references are completely internal to the class, where we have full control on how the field is accessed.

The getter is still the same as in Favor Optional Over Null. We convert the field into an Optional by calling Optional.ofNullable(). This goes hand in hand with the reset() method, which sets the field to null, because Optional.ofNullable(null) equals Optional.empty().

You might point out now that the getter and setter no longer match the JavaBeans conventions because their types differ. This can be a problem if you have to integrate with frameworks that rely on this convention. In this case, you’re forced to make do without Optional return types. Otherwise, Optional can still make your program more robust by avoiding null values.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.55.198