Either vs Try (vs Result)
Tags: kotlin, arrow, showdev
Published: 2021-11-16 12:59:34

Preguntas y respuestas sobre las [sesiones](https://dev.to/rogervinas/series/14723) *live coding* de [Arrow](https://arrow-kt.io/).

La siguiente pregunta fue realizada durante la [segunda sesión](https://dev.to/adevintaspain/gestion-de-errores-funcional-con-kotlin-y-arrow-2a93). Os dejamos también el enlace directo a la [discusión en Github](https://github.com/AdevintaSpain/wonderful-freshair-app/discussions/5).

## Pregunta
Para captura de excepciones presentasteis `Either<L,R>`.  Arrow incluye [`Try<T>`](https://arrow-kt.io/docs/0.10/apidocs/arrow-core-data/arrow.core/-try/) y la librería standard de Kotlin incluye [`Result<T>`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/).

Arrow ya tiene `Try` marcada como _deprecated_ porque no se alinea del todo con los principios de programación (paradigma?) que promueve Arrow.

La lib estándar de Kotlin incluye `Result` que parece una mezcla de `Try` y `Option`. Tampoco es demasiado limpio en mi opinión.

Hoy (en relación al 23 de septiembre) Alex Nedelcu ha hecho una [twitter poll](https://twitter.com/alexelcu/status/1440978686161915907) (ligeramente) relacionada con este tema.
{% twitter 1440978686161915907%} 

Podrías desarrollar los pros/cons de usar `Either` en comparación con las otras opciones que existen?

## Respuesta
Primero déjame establecer el contexto de nuestra respuesta, porque sin un contexto no hay explicación que se sostenga. En mi equipo en @adevintaeng desarrollamos aplicaciones distribuidas con [Kotlin](https://kotlinlang.org/). _Hemos encontrado valor en usar métodos monádicos en programación OO_. Nos interesa la componibilidad y la expresividad de tipos como `Either<L,R>` y los patrones de gestión de errores que facilita, cómo mostramos en esta segunda sesión. Desarrollando sistemas distribuidos sabemos que la gestión de errores, su diseño y su evolución, es la clave para crear aplicaciones resilientes y tolerantes al fallo.

En este contexto encontramos el uso de la librería [Arrow Core](https://arrow-kt.io/docs/core/) un perfecto compañero de viaje. Parte del trabajo de un ingeniero de software es asegurarse que las librerías que utiliza van a ser una ayuda para acelerar el desarrollo a la vez que no van a representar un problema en el futuro, como librerías no mantenidas o sin una estrategia de evolución sólida y solvente. En cuanto empezamos a utilizar Arrow `0.13.2`, el tipo `Try<T>` ya estaba obsoleto y eliminado desde la versión `0.11`. Y el tipo `Option<T>` estaba siendo cuestionado por los mismos creadores de Arrow. Así que recomendaban el uso de `Either<L,R>` desde la versión `0.13.2` para garantizar la compatibilidad total con la primera versión general de [Arrow `1.0.0`](https://www.47deg.com/blog/arrow-1-0-release/).

Desde el punto de vista de un programador que utiliza la librería para sus aplicaciones en producción, esta debería ser una explicación suficiente para utilizar `Either<L, R>` frente a las otras opciones. Pero podemos elaborar más las razones. 

`Try<T>` fue marcado cómo obsoleto en Arrow en el mismo momento que se decidió marcar cómo obsoleto `IO` monad y basar la estrategia de convertir las funciones con efectos laterales en funciones puras con el uso de Kotlin `suspend`. Marcando una función con `suspend` la ejecución de esa función devuelve una descripción del efecto, es decir el efecto no se produce si no la provees con un contexto, en este caso una [`Coroutine`](https://kotlinlang.org/docs/coroutines-overview.html). Si quieres profundizar más en el porqué, [aquí encontrarás el porque del cambio de estrategia](https://arrow-kt.io/docs/effects/io/).

Bien, que pasaba con `Try<T>`? El primer problema es que `Try` no podía diferir la ejecución del efecto de ningún modo y retornar únicamente una descripción del efecto porque sus constructores "evaluaban ansiosamente" - Dios, que difícil es intentar escribir en español sobre cualquier tema de ingeniería del software - a.k.a `eager evaluation` . Puedes ampliar detalles sobre los tipos de evaluación en [Lazy, eager and greedy evaluation](https://dev.to/drbearhands/lazy-eager-and-greedy-evaluation-43pf).

El segundo problema es que `Try<T>` no es seguro. Porqué? Básicamente porque puedes capturar cualquier `Throwable` que desees. Y si quieres tener control sobre una computación concurrente o paralela en la que se usa, no querrás que `Try<T>` pueda capturar `InterruptedException` o `CancellationException` entre otros.

Y éste es exactamente el mismo problema con [`Result<T>`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/) en Kotlin. De hecho, `Result<T>` es el tipo que se debe usar en vez de `Try<T>` para los caso de uso que así lo requieran.

Por todo esto, en Arrow se implementó [`Either.catch`](https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/-either/#eithercatch-exceptions), que es el camino a seguir para aislar nuestro código de librerías "impuras". 

En cuanto a `Option<T>` hubo bastante debate al respecto sobre si eliminar su uso en beneficio de un más idiomático - en Kotlin - [Nullable types](https://kotlinlang.org/docs/null-safety.html#nullable-types-and-non-null-types), porque se apreciaba poca aportación de valor sobre esto tipos. Además se indicaba que `Option<T>`no era más que (o si lo prefieres, es isomórfico a) 
>`typealias Option<A> = Either<Unit, A>`.

Pero después del [largo debate](https://github.com/arrow-kt/arrow-core/issues/114) @raulraja anunció que mantendrían `Option<T>` en Arrow Core `1.0.0` cómo así ha sido, porque existían algunos casos de uso en que todavía aportaba valor cómo con [RxJava](https://github.com/ReactiveX/RxJava/wiki/What's-different-in-2.0#nulls) que declara `Observable<T>` y no permite `null`.

Cómo ves, muchas de las razones se basan en cuestiones de la programación funcional cómo `lazy evaluation` o en cómo convertir en declarativos los efectos laterales de una función y diferir su ejecución en un entorno seguro. Nosotros todavía no estamos utilizando [`Arrow Fx`](https://arrow-kt.io/docs/fx/) ni estamos marcando nuestras funciones cómo `suspended`, pero lo haremos si le encontramos valor para nuestros casos de usos y por supuesto, lo explicaremos en otras sesiones.

Espero que haya podido aclarar un poco tus dudas. Y no dudéis en matizar o corregir algún punto que no haya explicado con claridad o que mi memoria haya hecho desviar de la verdad.  Obviamente, los que mejor pueden explicar esto son @raulraja, @47deg y los [contributors del proyecto Arrow](https://github.com/arrow-kt/arrow/graphs/contributors), a los que de paso, les doy las gracias por esta magnífica librería.

[![Ofertas Backend](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/nj85cjrphaqyozm0gq6d.png)](https://careers.adevinta.es/ofertas/?search=backend&stc=aff-blog%20dev.to-Either%20vs%20Try%20%28vs%20Result%29)