Reputation: 1781
I have the next code. As you may see there are 3 when
one inside another. Is it possible to flatten this code? I'm thinking about some wrapper but cannot get it. For now the only solution that I see is to move each when to the fun
like processFirstWhen
etc. Perhaps there is a cleaner solution. Any help appreciated.
when (val result = callback.invoke()) {
is DataCompletable.Success -> DomainCompletable.Success
is DataCompletable.Error ->
when (result.error) {
is DataError.Unauthorized ->
when (tokenMixIn.refresh()) {
is DomainCompletable.Success -> execute(
currentNumberOfRetries + 1,
callback
)
is DomainCompletable.Error -> DomainCompletable.Error(DomainError.RefreshFailed)
}
else -> DomainCompletable.Error(result.error.mapToDomain())
}
Upvotes: 3
Views: 6288
Reputation: 965
Nested when structures are difficult to understand because you can easily confuse the cases of an inner when as belonging to an outer statement. Therefore nested when statements should be avoided.
Specifically, you should structure your code to avoid the need for nested when statements, but if you cannot, then consider moving the inner when to another function.
when(val result =callback.invoke())
{
is DataCompletable.Success -> DomainCompletable.Success
is DataCompletable.Error ->
errorCallBack(result.error)
}
fun errorCallBack(val error:Error) {
when(error) {
is DataError.Unauthorized ->
when(tokenMixIn.refresh()) {
is DomainCompletable.Success -> execute(
currentNumberOfRetries + 1,
callback
)
is DomainCompletable.Error -> DomainCompletable.Error(DomainError.RefreshFailed)
}
else ->DomainCompletable.Error(result.error.mapToDomain())
}
}
Upvotes: 0
Reputation: 2931
Easy! But not using when
.
What I suppose is to replace it with flat hierarchy of if
's.
Like this:
val result = callback.invoke()
if(result is DataCompletable.Success) return DomainCompletable.Success
val error = result.error
if(error !is DataError.Unauthorized) return DomainCompletable.Error(result.error.mapToDomain())
val refreshResult = tokenMixIn.refresh()
if(refreshResult is DomainCompletable.Error) return DomainCompletable.Error(DomainError.RefreshFailed)
execute(currentNumberOfRetries + 1, callback)
Key aspect here is short-circuitness. We return result as soon as possible. But also we achieve flatter and easier to understand code.
Upvotes: 2