question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Dealing with unexpected exceptions more elegantly

See original GitHub issue

Whenever an unexpected exception gets thrown while evaluating a function with Result it leads to an unintuitive ClassCastException. Here is a simple example:

import com.github.kittinunf.result.Result
import org.junit.jupiter.api.Test
import kotlin.test.fail

internal class ResultExceptionClassCastTest {
    class MyException: Exception()

    @Test
    fun `Unexpected exception leads to unintuitive ClassCastException`() {
        Result.of<String, MyException> {
            operation("something")
        }.fold({}, {
            fail("Not reached")
        })
    }

    private fun operation(it: String): String {
        throw IllegalArgumentException()
        return "never reached $it"
    }
}

Is there something that I as a library user can do to handle this better? Is this an issue with the library?

The simple solution would be to expect an Exception (or Throwable!), and then to cast to the expected type, if it indeed is that type, but this doesn’t seem like a very good solution.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:7 (3 by maintainers)

github_iconTop GitHub Comments

3reactions
kittinunfcommented, Feb 9, 2019

I think there is very little we can do for this. Because in terms of Result, Result<T, E1> and Result<T, E2> are different types and represent different things. Unless you mark it as the top level type Result<T, Exception>.

Out of the top of my head, I think one possibility that I could make for this project is to relax the Error type of Result to be not dependent on the Exception or Throwable itself. Like, Result<T, E>, so that one can use the sealed class to represent Error like.

sealed class FindUserError {
    data class NotFound(val name: String) : FindUserError()
    data class MalformedName(val name: String) : FindUserError()
    data class FoundButHasBeenDeleted(val name: String) : FindUserError()
}

then one can use Result like

interface Repository {
  fun getUser(): Result<User, FindUserError> 
}

//usage
val result = dataSource.getUser()
when (result) {
  is Result.Failure -> {
    val error = result.error //FindUserError type
    //check each error type for appropriate UI display ...
  }
}

On the other hand, this looks like it moves Result to be something similar to Either type where there is already community support for this aka. Arrow. Worth to have another implementation or not, it probably depends on how one looks.

1reaction
Globegittercommented, Aug 22, 2019

@kittinunf I actually started using your library now and I started doing this:

typealias ResultFlow<T> = Flow<Result<T, ErrorMessage>>
typealias Result<T> = Result<T, ErrorMessage>
typealias Success<T> = Result.Success<T>
typealias Failure = Result.Failure<ErrorMessage>

sealed class ErrorClass : Exception("")
...

then it actually worked immediately with the code 😃 Having said that I would still prefer if the sealed class would not have to be a child of Exception just for the sake of it.

As a side note and bit off - topic, our API has started to center on Flows now as they are becoming stable and I built operators on top of ResultFlow, which I would be happy to contribute back here if there is interest.

Read more comments on GitHub >

github_iconTop Results From Across the Web

9 Best Practices to Handle Java Exceptions - Stackify
Handling Java exceptions isn't easy, especially for beginners. Read this post to understand exceptions and best practices for using them.
Read more >
Clean Code and the Art of Exception Handling - Toptal
Exceptions are as old as programming itself. An unhandled exception may cause unexpected behavior, and results can be spectacular.
Read more >
How to Handle Exceptions in Java - Rollbar
The best course of action is to explicitly handle those exceptions to recover from them gracefully. As we will see ahead, programming languages ......
Read more >
Elegant error handling with the JavaScript Either Monad
In JavaScript, we have a built-in language feature for dealing with exceptions. We wrap problematic code in a try…catch statement. This lets us ......
Read more >
Learning (not) to Handle Exceptions - Python for the Lab
Exceptions are a crucial part of any code, and dealing with them elegantly can improve a lot the value of your code.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found