Android-CleanArchitecture-Kotlin icon indicating copy to clipboard operation
Android-CleanArchitecture-Kotlin copied to clipboard

Either vs Sealed class

Open mateherber opened this issue 7 years ago • 14 comments

Hi @android10, long time no see :)

I really enjoyed reading the new post, this seems pretty lean but also robust approach.

Wanted to ask about the Either type. I had a "Result" class in my mind of the following:

sealed class Result<out T : Any>

sealed class Failure(val throwable: Throwable) : Result<Nothing>()

data class Success<out T : Any>(val value: T) : Result<T>()

fun test() {
    val result: Result<String> = Success("test")

    when (result) {
        is Failure -> print(result.throwable)
        is Success -> print(result.value)
    }
}

For me this has a nicer syntax (also could add the either extension methods with the blocks) and I don't see the benefits of the Either after thinking for several minutes. Of course this is up to personal taste I just wanted to ask for an opinion or check whether I missed some cool aspects between the lines :)

mateherber avatar May 10 '18 11:05 mateherber

Also Dmitry Jemerov in his presentation "Ideomatic Kotlin" suggest to use sealed classes over solutions as "Either". Maybe the benefit will be better code readability...

ghost avatar May 10 '18 11:05 ghost

I personally think that Either should be used, but hidden as a typealias Result.

Previously I've used something akin to the Success/failure result portrayed here.

Zhuinden avatar May 10 '18 12:05 Zhuinden

@mateherber I've used your proposed Result version on several occations, but I find it usually clutters the code at the call site.

One of the points of using Either (which btw also is a sealed class) is that it is a general purpose class that you can use whenever you can have exactly one of two possible return values, not a specific Result/Failure class. The either function also removes the need to use an extra when clause in any other places, a more functional approach if you will.

You can, as you say, add extension functions to Result/Failure, but then you've almost arrived at the point where you have a less flexible version of Either.

In the end though I agree with you on the point that it's mostly a matter of personal taste. =)

Qw4z1 avatar May 10 '18 14:05 Qw4z1

@Qw4z1 how about a typealias over Either and call it Result via typealias?

Zhuinden avatar May 10 '18 16:05 Zhuinden

@Zhuinden looks good to me

RPallas92 avatar May 10 '18 16:05 RPallas92

@Zhuinden I like typealiases in general. I use them wherever it helps future me grasp the context more easily. This is one of those cases where it could be used and could make sense in the context of the UseCase.

Qw4z1 avatar May 13 '18 13:05 Qw4z1

I would suggest to use Try monad instead of Either. It is like Either but instead of left/right it contains success/failure. The code will be more readable. Here is a sample of realization written in Scala. https://mauricio.github.io/2014/02/17/scala-either-try-and-the-m-word.html

zyvpeople avatar May 16 '18 08:05 zyvpeople

Try usage is when you wanna deal with throwables and exceptions you have no control over. That's the reason behind Either<T>

android10 avatar May 16 '18 11:05 android10

I haven't heard this statement before. We use such monads like Optional, Either, Try to transform non-pure functions that throw exceptions into pure ones. And these monads are only differ in the way of deliver error to the user. Of course, Either fits our needs but Try is special case of Either monad for dealing with exceptions. Authors of Scala added Try later (version 2.10) than Either (version 2.7) to make code more readable - it is much more obvious to check for success/fail instead of left/right. But it is up to you what approach to choose)

zyvpeople avatar May 16 '18 12:05 zyvpeople

@zyvpeople Either is definitely a multi-purpose type but it's widely used for error handling, especially in the Scala community...The reason?

You can use Either for exception handling very much like Try. Either has one advantage over Try: you can have more specific error types at compile time, while Try uses Throwable all the time. This means that Either can be a good choice for expected errors.

That is what I followed which does not mean that Try does not have a place in this codebase. Of course we can use it as soon as it fulfills our needs. And by the way, that is the idea and would be nice to start growing this codebase and address different real world problems.

android10 avatar May 17 '18 08:05 android10

Agree with you. If you need specific error types (not only Throwable) so the Either is the best choice.

zyvpeople avatar May 17 '18 08:05 zyvpeople

i have some question. about Either class sealed class Either<out L, out R>. It is same with Pair in kotlin ? @android10

ariefannur avatar Jun 11 '18 13:06 ariefannur

You can use Either for exception handling very much like Try. Either has one advantage over Try: you can have more specific error types at compile time, while Try uses Throwable all the time. This means that Either can be a good choice for expected errors.

can you please provide me some refrences on it? I want to read in details

aaghan avatar Apr 28 '20 06:04 aaghan

From the future, I wouldn't bring in an Either for this and just use a sealed class per each usecase.

I guess that's the opposite of what I claimed 2 years ago, overall it depends on how you want to communicate N potential expected errors.

Zhuinden avatar Apr 28 '20 10:04 Zhuinden