There were already quite a few discussions on Stackoverflow about proper ways of using Optional in Java (Discussions like this one, or this)
As of now, using Optional for class members in Java is widely recognized as a code smell and even discouraged by fact that it deliberately does not implement Serializable interface. Also, we should avoid it in DTOs, constructors and methods' input parameters. From OOP point of view everything I have read so far about Optional appeals to my reason.
My question is, does FP side of Scala change something in a way we should use Optional ? Especially since implementation of Optional in Scala seems to be way richer. I have found plenty of articles describing how to use it in Scala, but not a single one that exhaust topic when should I use it and when should I not.
Option of scala implements Serializable
Usage of
Option
in scala is highly recommended for nullable attributes.Option[T]
is considered better thanT
because the former is more typesafe than than latter.on the contrary presence of
null
in-place of Optional attribute in scala is considered a code-smell.As much as Scala is a functional language it also a language that promotes type-safety. In an Ideal world a truly fully typesafe language will not have runtime exceptions like
NullpointerException
andOption
plays a important role in Scala to avoid it.The Option[T] explicits states that the attribute can be in the state of null (i.e.
None
) and forces the clients of the attribute to handle thenull
scenario. Thus Option adds more information to the type system and makes the code more typesafe.With language feature such as such as pattern matching and Monad/Monoid the economics of using Optional datatypes in Scala is very cheap and user friendly in Scala compared to Java.
Pattern matching:
Option as Monad:
Edit:
Jubobs makes very good case where using Option can be replaced with custom types. But I think there are many more cases where Optional attributes make more sense. For eg: If the Account object has optional attributes such as
emailId
andphoneNo
then Option[T] would be a better solution since creating custom types for each combination would be impractical and would lead to class explosion.Short answer
Option
fields have use cases; they're not intrinsically bad. However, even though several well established libraries (e.g. ScalaTest) define classes withOption
fields, the latter, IMO, tend to be a code smell, as they often try to do too much for their own good.In many cases, a type containing optional fields can easily and advantageously be replaced by an algebraic data type.
An example
The domain
Consider a business domain dealing with accounts. An account starts its life one day as an open account, but may eventually be closed. Accounts, among other data, contains the dates on which they were open and closed, where applicable.
Using an
Option
fieldHere is an implementation of an account, using an
Option
field:We also have an account service, which defines, among other things, a
close
method:This approach is problematic, for a number of reasons. One problem is that
Account
isn't particularly performant: becauseclosedOn
is a "boxed" type, you have one level of indirection too many, so to speak. Moreover,Account
's memory footprint is less than ideal: a "closed account" contains a pretty uninteresting value (None
), which is a waste of space.Another, more serious, problem is that the
close
method cannot enforce, at the type level, that the parameter be an "open account" and the result be a "closed account". You would have to write tests to check that this business rule is enforced by your implementation.Using a small ADT (and eschewing
Option
fields)Consider the following alternative design:
This small ADT remedies the performance problem, but there is more... You can now encode the business rule at the type level! This is an example of making illegal states unrepresentable (a phrase attributed to Yaron Minsky). As a result, your service's API becomes more expressive and harder to misuse:
This example may be sufficient to convince you that the second approach is preferable, and that
Option
fields are best avoided (or, at least, used sparingly).Resources
For more more about eliminating optional fields towards making illegal states unrepresentable, see