0Pricing
Kotlin Academy · Lekcja

Either<L, R>: typowana obsługa błędów bez wyjątków

Użyj Either do reprezentowania powodzenia i niepowodzenia bez zgłaszania wyjątków.

Either<L, R>: typowana obsługa błędów bez wyjątków to bezpłatna lekcja Kotlin Academy na CoddyKit. To lekcja 1 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Kotlin Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Problem z wyjątkami w logice biznesowej

Wyjątki są przeznaczone do obsługi nieoczekiwanych awarii (null pointer, błąd wejścia-wyjścia). Używanie ich do sygnalizowania oczekiwanych niepowodzeń biznesowych (błąd walidacji, „nie znaleziono”) sprawia, że przepływ sterowania staje się niewidoczny, wymusza używanie try/catch w każdym miejscu wywołania i ukrywa błędy w sygnaturach funkcji.

Czym jest Either<L, R>?

Either to typ sumy z dwoma przypadkami: Left(value: L) konwencjonalnie przechowuje błąd, a Right(value: R) — wartość oznaczającą powodzenie. Funkcja zwracająca Either jawnie wskazuje w swojej sygnaturze możliwość niepowodzenia.

Either w Arrow

Należy dodać Arrow do projektu, aby uzyskać Either i pełny ekosystem jego operatorów:

// build.gradle.kts
implementation("io.arrow-kt:arrow-core:1.2.4")

// Usage
import arrow.core.Either
import arrow.core.left
import arrow.core.right

Zwracanie Either z funkcji

W przypadku powodzenia należy zwrócić value.right(), a w przypadku niepowodzenia — error.left(). Wywołujący musi obsłużyć obie gałęzie:

sealed class UserError { object NotFound : UserError(); data class InvalidEmail(val msg: String) : UserError() }

fun findUser(id: Long): Either<UserError, User> =
    if (id <= 0) UserError.NotFound.left()
    else User(id, "Alice").right()

Obsługa Either za pomocą fold

Należy użyć fold(ifLeft, ifRight), aby obsłużyć oba przypadki w jednym wyrażeniu:

val result = findUser(1L)
val message = result.fold(
    ifLeft  = { error -> "Error: $error" },
    ifRight = { user  -> "Found: ${user.name}" }
)
println(message)

Przekształcanie wartości Right za pomocą map

map { } przekształca wartość Right, nie zmieniając Left. Dzięki temu Either jest funktorem — można bezpiecznie łączyć przekształcenia:

val nameResult: Either<UserError, String> = findUser(1L).map { it.name }

Łączenie za pomocą flatMap

flatMap { } łączy obliczenia, które same zwracają Either. Jeśli dowolny krok zwróci Left, łańcuch zostanie przerwany, a błąd propagowany bez wykonywania kolejnych kroków:

fun validateEmail(email: String): Either<UserError, String> =
    if (email.contains("@")) email.right()
    else UserError.InvalidEmail("bad format").left()

fun createUser(email: String): Either<UserError, User> =
    validateEmail(email).flatMap { validEmail ->
        User(1L, validEmail).right()
    }

Either.catch do opakowywania wyjątków

Either.catch { } wykonuje blok i opakowuje każdy wyjątek jako Left. Należy używać go na granicy między starszym kodem, który zgłasza wyjątki, a domeną opartą na Either:

val result: Either<Throwable, User> = Either.catch {
    userRepository.findOrThrow(id)
}

Odzyskiwanie za pomocą getOrElse i orElse

getOrElse { default } wyodrębnia wartość Right albo zwraca wartość domyślną. orElse { alternativeEither } zastępuje Left innym obliczeniem:

val user: User = findUser(0L).getOrElse { User(-1L, "Guest") }
val user2: Either<UserError, User> = findUser(0L).orElse { User(99L, "Default").right() }

Dopasowywanie wzorców za pomocą when

Należy użyć when na klasie zapieczętowanej w stylu Either albo bezpośrednio na Either za pomocą is Either.Left / Either.Right, aby wyczerpująco obsłużyć wszystkie przypadki:

when (val r = findUser(1L)) {
    is Either.Left  -> println("Error: ${r.value}")
    is Either.Right -> println("User: ${r.value.name}")
}

Either w warstwach usług

Należy zwracać Either z funkcji repozytorium i usług. Należy mapować je na odpowiedzi HTTP na poziomie tras Ktor, utrzymując logikę biznesową niezależną od szczegółów frameworka:

get("/users/{id}") {
    val id = call.parameters["id"]?.toLongOrNull() ?: return@get call.respond(HttpStatusCode.BadRequest)
    userService.findById(id).fold(
        ifLeft  = { call.respond(HttpStatusCode.NotFound) },
        ifRight = { call.respond(it) }
    )
}

Szybkie sprawdzenie

Co robi flatMap { } dla wartości Either.Left?

Podsumowanie: Either<L, R>

Najważniejsze informacje:

  • Either jawnie wskazuje ścieżkę niepowodzenia w sygnaturze funkcji
  • Right = powodzenie; Left = niepowodzenie (zgodnie z konwencją)
  • map { } — przekształca wartość oznaczającą powodzenie; flatMap { } — łączy obliczenia, które mogą zakończyć się niepowodzeniem
  • fold(ifLeft, ifRight) — obsługuje oba przypadki w jednym wyrażeniu
  • Either.catch { } — opakowuje kod zgłaszający wyjątki na granicach systemu

Często zadawane pytania

Czy lekcja „Either<L, R>: typowana obsługa błędów bez wyjątków” jest bezpłatna?

Tak — pełny tekst „Either<L, R>: typowana obsługa błędów bez wyjątków” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Kotlin Academy, przejdź na CoddyKit PRO. Kurs Kotlin Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Either<L, R>: typowana obsługa błędów bez wyjątków”?

Użyj Either do reprezentowania powodzenia i niepowodzenia bez zgłaszania wyjątków. Ćwiczysz Kotlin Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Kotlin Academy?

Nie wymagamy żadnego doświadczenia. Kotlin Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 1 z 4.

Ile czasu zajmuje lekcja „Either<L, R>: typowana obsługa błędów bez wyjątków”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Kotlin Academy?

Tak. Każda lekcja Kotlin Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Either : typowana obsługa błędów bez wyjątków
  2. DSL Raise w Arrow: składanie typowanych błędów
  3. Option i nullable: kiedy używać każdego z nich
  4. Funkcjonalne modelowanie domeny za pomocą typów podstawowych Arrow
← Powrót do Kotlin Academy