Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 506 Vote(s) - 3.67 Average
  • 1
  • 2
  • 3
  • 4
  • 5
When and how to use Result in Kotlin?

#1
I love the idea of Result.
I love having encapsulated try/catch.

But I’m a little confused about how and when to use Result.

I currently use it like this:

My adapters and services return a Result. Failures and stacktraces are logged but do nothing else

runCatching{
.... // do something cool
}.onFailure {
logger.error("Something bad happened ", it)
}

My Resource classes fold and handle the Result

return service.method().fold(
onFailure = {
Response.serverError().entity("Oops").build()
},
onSuccess = {
Response.ok().entity(doSomethingWith(it)).build()
}
)
Is this really the correct way to use a Result? Or is there a more idiomatic way to code in Kotlin?
Reply

#2
**TL;DR:** never in business code (prefer custom sealed classes), but you can consider `Result` if you build a framework that must relay all kinds of errors through a different way than the exception mechanism (e.g. kotlinx.coroutines's implementation).
___

First, there is actually a [list of use cases](

[To see links please register here]

) for the motivation of the initial introduction of `Result`, if you find it interesting. Also in the same document:

> The Result class is designed to capture generic failures of Kotlin functions for their latter processing and should be used in general-purpose API like futures, etc, that deal with invocation of Kotlin code blocks and must be able to represent both a successful and a failed result of execution. The Result class is not designed to represent domain-specific error conditions.

Also, [here is a very nice article](

[To see links please register here]

) by Roman Elizarov about exceptions in Kotlin and more specifically when to use the type system instead of exceptions.

Most of what follows is my personal opinion. It's built from facts, but is still just an opinion, so take it with a grain of salt.

### Do not use `runCatching` or catch `Throwable` in business code

Note that `runCatching` catches all sorts of `Throwable`, including JVM `Error`s like `NoClassDefFoundError`, `ThreadDeath`, `OutOfMemoryError`, or `StackOverflowError`. There is usually almost nothing you can do with such JVM errors (even reporting them might be impossible, for instance in case of OOME).

According to the Java documentation, the [Error](

[To see links please register here]

) class *"indicates serious problems that a reasonable application should not try to catch"*. There are some very special cases where you might want to *try* to recover from error, but that is quite exceptional (pun intended).

Catch-all mechanisms like this (even `catch(Exception)`) are usually not recommended unless you're implementing some kind of framework that needs to attempt to report errors in some way.

So, if we don't *catch* errors (and instead let them bubble up naturally), `Result` isn't part of the picture here.

### Do not catch programming exceptions in business code

Apart from JVM errors, I believe exceptions due to programming errors shouldn't really be handled in a way that bloats the business code either. Using `error()`, `check()`, `require()` in the right places will make use of exceptions to detect bugs that cannot be caught by the compiler (`IllegalStateException`, `IllegalArgumentException`). It often doesn't make sense to catch these exceptions in business code, because they appear when the programmer made a mistake and the logic of the code is broken. You should instead fix the code's logic.

Sometimes it might still be useful to catch all exceptions (including these ones) around an area of code, and recover with a high level replacement for the whole failed operation (usually in framework code, but sometimes in business code too). This will probably be done with some `try-catch(Exception)`, though, but `Result` will not be involved here because the point of such code would be to delimit with `try-catch` the high-level operation that can be replaced. Low-level code will not return `Result` because it doesn't know whether there are higher level operations that can be replaced with something in case of programming errors, or if it should just bubble up.

### Modeling business errors

That leaves business errors for result-like types. By business errors, I mean things like missing entities, unknown values from external systems, bad user input, etc. However, I usually find better ways to model them than using `kotlin.Result` (it's not meant for this, as the design document stipulates). Modelling the absence of value is usually easy enough with a nullable type `fun find(username: String): User?`. Modelling a set of outcomes can be done with a custom sealed class that cover different cases, like a result type but with specific error subtypes (and more interesting business data about the error than just `Throwable`).

So in short, in the end, I never use `kotlin.Result` myself in business code (I could consider it for generic framework code that needs to report all errors).

----

> My adapters and services return a Result. Failures and stacktraces are logged but do nothing else

A side note on that. As you can see, you're logging errors in the service itself, but it's unclear from the service consumer's perspective. The consumer receives a `Result`, so who's reponsible with dealing with the error here? If it's a recoverable error then it may or may not be appropriate to log it as an error, and maybe it's better as a warning or not at all. Maybe the consumer knows better the severity of the problem than the service. Also, the service makes no difference between JVM errors, programming errors (IAE, ISE, etc.), and business errors in the way it logs them.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through