I love oneliners.
But, only when it’s combined with lots of functions.
norma functions
When you use normal functions, you can get away with having bigger functions.
private fun updateStatus(id: String, status: Status) : StateHaver{
val oldStateHaver = getById(id)
if(oldStateHaver.status in prohibitedStatuses)
throw ProhibitStatusChangingException(status, prohibitedStatuses)
oldStateHaver.status = status
val newStateHaver = repository.save(oldStateHaver)
logger.info {
newStateHaver.run{ “New status. id $id: $status” }
}
return newStateHaver
}
inline functions
But, when you’re writing with oneliners, this doesn’t look well.
This makes that you need to do more work to make it look acceptable.
The most important reason is that you’re not chaining two actions, but two implementations.
The actions are updating and checking if it’s valid.
for checking it’s valid, you could use classes:
fun StateHaver.asValidOrNull() = ValidStateHaver.orNull(this)
class ValidStateHaver private constructor (val stateHaver : StateHaver){
companion object{
fun orNull(
prohibitedStates : List<States>
) = when(status in prohibitedStateHaver){
true -> null
false -> ValidStateHaver(this)
}
}
You can create a function to the valid state do do the real updating:
private fun ValidStateHaver.updateStatusTo(status : Status) : StateHaver{
this.status = status
return repository.save(this).apply{
logger.info {"New status. id $id : $status" }
}
}
Now your function becomes:
private fun updateStatus(id: String, status: Status) = getById(id)
.asAllowedOrNull(prohibitedStatuses = prohibitedStatuses)
?.updateStatusTo(status)
?: throw ProhibitStatusChangingException(status, prohibitedStatuses)
closing remarks
Now, you can’t forget to check as it simply won’t compile.
I choose for safety, but you could choose for memory/speed with inline classes.
Overkill? just make your code look a bit more similar to the last. Or ignore everything I typed