miqbaldc
02/03/2022, 1:55 PM1️⃣orpreconditions
for this case, maybe any references?throw
suspend fun updatePushToken(newPushToken: String): Result<String> = invoke {
require(newPushToken.isNotEmpty()) { "Push token is required to not empty" }
kotlin.runCatching { repository.agentUpdatePushToken(newPushToken = newPushToken) }
}
or
2️⃣
suspend fun updatePushToken(newPushToken: String): Result<String> = invoke {
if (newPushToken.isEmpty()) {
throw IllegalArgumentException("Push token is required to not empty")
}
kotlin.runCatching { repository.agentUpdatePushToken(newPushToken = newPushToken) }
}
Joffrey
02/03/2022, 1:57 PMrunCatching
in this context, and certainly not fully qualified like this. Why do you want to catch OutOfMemoryError
, NoClassDefFoundError
and other such throwables when calling agentUpdatePushToken
, but you're fine throwing IAE 2 lines above this?miqbaldc
02/03/2022, 2:33 PMUseCase
(class), here’s the full snippet:
class AgentPushTokenNotificationUseCase @Inject constructor(
private val repository: AccountRepository, // remote or local switch in the implementation detail
dispatchers: CoroutineDispatchers,
) {
suspend fun updatePushToken(newPushToken: String): Result<String> = withContext(dispatchers) {
require(newPushToken.isNotEmpty()) { "Push token is required to not empty" }
kotlin.runCatching { repository.agentUpdatePushToken(newPushToken = newPushToken) }
}
}
Joffrey
02/03/2022, 2:36 PMinvoke
here? Your class doesn't seem to extend any function type.
Also, I don't believe this answers my points about runCatching
🤔miqbaldc
02/03/2022, 2:41 PMrunCatching
part intention was to consider as a tolerable failures (such any kind of throwable) in our case (and we transform it into a Result.failure(…)
), and in a UI Layer, we can shows some sort of events/effect (e.g: showing a dialog in this case)What’shere? Your class doesn’t seem to extend any function type.invoke
Joffrey
02/03/2022, 2:44 PMkotlin.Result
type was not meant to represent business errors. Please take a look at this:
https://stackoverflow.com/questions/70847513/when-and-how-to-use-result-in-kotlinmiqbaldc
02/03/2022, 3:32 PMrunCatching
or an operator such as Flow.catch
for error handling in the consumer side (e.g: UI Layer)?ephemient
02/03/2022, 7:14 PMmiqbaldc
02/05/2022, 7:21 AMsealed class AgentNotificationsResult {
object EmptyNewPushToken : AgentNotificationsResult()
data class FailUpdatePushToken(val e: Exception) : AgentNotificationsResult()
object SuccessUpdatePushToken : AgentNotificationsResult()
}
class AgentNotificationsUseCase @Inject constructor(
private val repository: AccountRepository,
private val dispatchers: CoroutineDispatchers = Default,
) {
suspend fun updatePushToken(newPushToken: String): AgentNotificationsResult = withContext(dispatchers) {
if (newPushToken.isEmpty()) {
AgentNotificationsResult.EmptyNewPushToken
}
try {
repository.agentUpdatePushToken(newPushToken = newPushToken)
AgentNotificationsResult.SuccessUpdatePushToken
} catch (e: Exception) {
AgentNotificationsResult.FailUpdatePushToken(e = e)
}
}
}
Not sure for thepart that catching generaltry-catch
is considered as “business error”, as it’ll catchException
orretrofit2.HttpException
fromSocketTimeoutException
layer.:data
There’s an article mentioning about transforming theexception to a `sealed class`/`inteface` as well in here::data
(thehttps://miro.medium.com/max/1400/1*0HepdkVU-3zhoXBD2R0aLw.png▾
has a specific result type and exception in this case):base
Matteo Mirk
02/08/2022, 10:55 AMrequire()
will throw an IAE so they’re equivalent. I would choose [1]