A higher order function to simplify Java builders usage
I was working with auth0’s java library to issue and verify JWT tokens. The library is easy to use and pretty strait-forward. At some point, I had a Kotlin code to issue a JWT token:
The code is trivial. I create a new JWT token and fill claims with some data.
I put a claim only if a respective data is not null
.
The code above is long and hard to read. Typically, one writes it with a copy-paste
approach. I’m not an exception here too. I even did a typoe copying
things: "userId"
is used twice:
And that I had before pic.twitter.com/2grxbvpKnP
— Eugene Petrenko (@jonnyzzz) July 10, 2018
Immutability
The best programs, so far, are immutable programs. Let’s make the builder
variable immutable.
Here is the trick I like in Kotlin. Usually, a builder function returns a builder instance, e.g.
You never know, if a returned Builder
is the same as the Builder
you call a with*()
method on. As of Builder
implementation, it is hard to return a new instance of a
builder every time. People tend
to return this
from builder functions, it is just easier and does not require tricks.
I see the dilemma here. Do we assume the Builder
is mutable or not?
Kotlin data classes and copy(...)
function
makes it easier, no you know it.
Mutable Builder
Let’s assume the Builder
returns this
from with*(...)
methods.
And trivially, we may turn the builder
variable to be immutable
and call with*(...)
methods:
I do not like that assumption. A sudden change of the builder implementation will introduce a hard to find a bug in the code.
Immutable or Mutable Builder
Now, let’s assume we have no assumptions on Builder
implementation. It is
allowed and not forced to return same this
from a with*()
functions. We still need either
a mutable variable builder
or a longer expression.
Expression and Extension Functions
But, here we need a function call that takes Builder
as the receiver,
aka extension function,
and the function should check and call something in the builder.
I created the following function:
That one allows me to turn the whole method into:
I like that one. It is shorted and read better!
Reflection and Callable References
I got the question from my friend on Twitter
Is it possible to get rid of strings, too?
Is it possible to get rid of strings, too?
— Eugeny Schepotiev (@zeckson) July 11, 2018
It is possible, for that, you use property references and KProperty to grab property name at the runtime:
Here I use principal::userId
and principal::serviceId
to pass both the property name
and the function to get the property value. It makes the code shorter.
We do not have the explicit names anymore.
One should understand the risk. A sudden
refactoring and rename of userId
or serviceId
properties of the principal
class
will change the names we use in the builder. It may
cause trouble on a production. Several unit
tests (or integration tests) will help to preserve the API.
The same trick with callable references works for functions too. You might check the whole documentation page on reflection in Kotlin.
I checked, and it is not required (at least with Kotlin/JVM v1.2.51) to have kotlin-reflect
library to make the example above
work.