Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

https://github.com/Subito-it/Esito

Esito ambition is to be your return type for suspending functions.
https://github.com/Subito-it/Esito

android functional-programming kotlin result retrofit

Last synced: 3 months ago
JSON representation

Esito ambition is to be your return type for suspending functions.

Lists

README

        

# Esito

[![](https://jitpack.io/v/Subito-it/Esito.svg)](https://jitpack.io/#Subito-it/Esito)

Coroutines are great for Asynchronous and non-blocking programming, but exceptions could be hard to handle, especially in a coroutine. [[1](https://kt.academy/article/cc-exception-handling), [2](https://medium.com/androiddevelopers/exceptions-in-coroutines-ce8da1ec060c), [3](https://www.netguru.com/blog/exceptions-in-kotlin-coroutines)]

Exceptions in a coroutine could cancel their parents, and each canceled parent cancels all its children, and this is not always the desired behavior.

While this could be changed using a `SupervisorJob`, it's still easy to shoot yourself in the foots throwing exceptions in Coroutines, so Esito is proposing an alternative approach making explicit the computations that could fail.

## Installation

```groovy
repositories {
maven { url 'https://jitpack.io' }
}

dependencies {
implementation("com.github.Subito-it.Esito:core:(insert latest version)")
}
```

### Getting started

The main class is the sealed class [`Result`](core/src/main/kotlin/it/subito/esito/core/Result.kt), with two subtypes:

- `Success`: it contains the result of a successful computation
- `Failure`: it contains the cause of an unsuccessful computation

The goal when using Esito is to avoid throwing exceptions and use Result as the return type of a function that can fail:

```kotlin
sealed class ConversionError
object EmptyInput : ConversionError()
object NotNumericInput : ConversionError()

fun fromStringToInt(input: String): Result = when {
input.isBlank() -> Result.failure(EmptyInput)
else -> runCatching { input.toInt() }.mapError { NotNumericInput }
}
```

In this example we are defining all the possible failures in `ConversionError`, then we are applying some logic to build our result.

If the input is not blank we are using the `runCatching` method to wrap a method throwing an exception and mapping the eventual error in our desired type.

### Operators

Esito result has several operators, such as `map` and `flatmap`, for examples see [Recipes](Recipes.md).

## Retrofit Integration

Esito ships an integration with retrofit, after a one-line setup you can start to use Result return type in your Retrofit interfaces:

```kotlin
interface GitHubService {

@GET("users/{user}/repos")
suspend fun listRepos(@Path("user") user: String?): Result, Throwable>
}
```

For additional info and to learn how to use your own Error instead of Throwable have a look at [this documentation](/retrofit/README.md).

## Async Utilities

Esito offers some utilities for suspending methods returning Result. For example, suppose we have the following functions:

```kotlin
suspend fun getUserFullName(userId: Int): Result

suspend fun getUserStatus(userId: Int): Result

```

And we have to return an instance of DataForUI running in parallel `getUserFullName` and `getUserStatus`.

```kotlin
data class DataForUI(
val userFullName: String,
val userStatus: UserStatus
)
```

Esito exposes a `zip` method to compute two independent execution in parallel:

```kotlin
suspend fun fetchIfo(userId: Int): Result =
zip(
{ getUserFullName(userId) },
{ getUserStatus(userId) },
::DataForUI //syntactic sugar for constructor
).invoke()
```
For additional info have a look at this [documentation](async/README.md).

## Testing

Esito is providing two extension methods to facilitate testing: `assertIsSuccess` and `assertIsFailure`, here is an example of usage:

```kotlin
val success = Result.success(42)
success.assertIsSuccess {
assertEquals(42, value)
}

val failure = Result.failure(RuntimeException("Ops"))
failure.assertIsFailure {
assertEquals("Ops", error.message)
}
```
For additional info have a look at this [documentation](test/README.md).