I was thinking about null
s in configuration files. Part of the problem is that you cannot use Optional<T>
in the configuration definition, so all of your configuration is implicitly optional (i.e. it could be null). It would be nice to have missing fields be treated as a configuration-time error. If we wanted optional ones, we would explicitly state Optional<ElasticSearchConfig>
. Of course, there are also some cases where you actually want an arbitrary set of completely optional parameters (HTTP clients come to mind). In this case I guess you'd have a lot of Optional<T>
, but it's worth it, because you won't accidentally assume that its non-optional.
Below is how I'd do the specific problem of a Logger with an optional configuration file. I assume our configuration utility is sophisticated enough to give us Optional<T>
.
Notice that ILogger
implements a monoidal structure: it has a plus
, a zero
and satisfies the law ∀x. x.plus(zero) = x
. This makes it easy to expand logging functionality in a clean way. You just plus
a bunch of untangled logger logic together into one. This architecture garuntees you won't have interference between the loggers (modulo exceptions, etc.).
It's also nice that the configuration gives you a maybeEsc
directly so there's no way you can accidentally forget that a parameter is optional (because the type system will complain that you have an Optional<ElasticSearchConfig>
not an ElasticSearchConfig
).
In fact, the ILogger interface is actually a commutative monoid since
∀x,y. x.plus(y) = y.plus(x)
.