Kotlin Academy · Oppitunti

Either<L, R>: tyypitetty virheenkäsittely ilman poikkeuksia

Käyttäkää Either-tyyppiä onnistumisen ja epäonnistumisen esittämiseen ilman poikkeusten heittämistä.

Oppitunti 1/413 vaihetta

Either<L, R>: tyypitetty virheenkäsittely ilman poikkeuksia on ilmainen Kotlin Academy-oppitunti CoddyKitissä. Tämä on oppitunti 1/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu Kotlin Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.

Poikkeusten ongelma liiketoimintalogiikassa

Poikkeukset on tarkoitettu odottamattomille virheille (null-osoitin, I/O-virhe). Jos niitä käytetään odotettujen liiketoimintavirheiden (validoinnin epäonnistuminen, "ei löytynyt") ilmaisemiseen, ohjelman suorituspolku muuttuu näkymättömäksi, jokaisessa kutsukohdassa tarvitaan try/catch ja virheet jäävät piiloon funktioiden allekirjoituksissa.

Mikä on Either<L, R>?

Either on summatyyppi, jolla on kaksi tapausta: Left(value: L) sisältää yleensä virheen ja Right(value: R) onnistuneen tuloksen. Either-tyypin palauttavan funktion allekirjoituksessa epäonnistumisen mahdollisuus ilmaistaan selkeästi.

Arrow'n Either

Lisätkää Arrow projektiinne, jotta saatte käyttöön Either-tyypin ja sen kattavan operaattorien ekosysteemin:

// 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

Eitherin palauttaminen funktiosta

Palauttakaa onnistumisen tapauksessa value.right() ja epäonnistumisen tapauksessa error.left(). Kutsujan on käsiteltävä molemmat haarat:

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()

Eitherin käsittely fold-funktiolla

Käyttäkää fold(ifLeft, ifRight) -funktiota molempien tapausten käsittelyyn yhdessä lausekkeessa:

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

Right-arvon muuntaminen map-funktiolla

map { } muuntaa Right-arvoa koskematta Left-arvoon. Tämän ansiosta Either on funktori — voitte ketjuttaa muunnoksia turvallisesti:

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

Ketjuttaminen flatMap-funktiolla

flatMap { } ketjuttaa laskutoimituksia, jotka itse palauttavat Either-arvon. Jos jokin vaihe palauttaa Left-arvon, ketju keskeytyy ja virhe välitetään eteenpäin suorittamatta seuraavia vaiheita:

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 poikkeusten käärimiseen

Either.catch { } suorittaa lohkon ja käärii kaikki poikkeukset Left -arvoksi. Käyttäkää sitä rajapinnassa sellaisen vanhan koodin ja Either-pohjaisen toimialueen välillä, joka heittää poikkeuksia:

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

Palautuminen getOrElse- ja orElse-funktioilla

getOrElse { default } poimii Right-arvon tai palauttaa oletusarvon. orElse { alternativeEither } korvaa Left-arvon toisella laskutoimituksella:

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

Kuviovastaavuus when-lauseella

Käyttäkää when-lausetta sealed-tyyppisen Either-tyyppisen luokan kanssa tai suoraan Either-tyypin kanssa käyttämällä muotoa is Either.Left / Either.Right, jotta kaikki tapaukset käsitellään kattavasti:

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

Either palvelukerroksissa

Palauttakaa Either repository- ja palvelufunktioista. Muuntakaa se HTTP-vastauksiksi Ktor-reittitasolla, jolloin liiketoimintalogiikka pysyy erillään frameworkin yksityiskohdista:

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) }
    )
}

Pikatarkistus

Mitä flatMap { } tekee Either.Left -arvolle?

Yhteenveto: Either<L, R>

Keskeiset opit:

  • Either tekee epäonnistumisen polun näkyväksi funktion allekirjoituksessa
  • Right = onnistuminen; Left = epäonnistuminen (sopimuksen mukaan)
  • map { } — muuntaa onnistuneen arvon; flatMap { } — ketjuttaa epäonnistuvia laskutoimituksia
  • fold(ifLeft, ifRight) — käsittelee molemmat tapaukset yhdessä lausekkeessa
  • Either.catch { } — käärii poikkeuksia heittävän koodin rajapinnoissa
Aloita maksutta

Opi Kotlin tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
51
Oppitunnit
203

Usein kysytyt kysymykset

Onko oppitunti ”Either<L, R>: tyypitetty virheenkäsittely ilman poikkeuksia” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa Kotlin Academy-oppimispolun 3 oppituntia, myös oppitunnin “Either<L, R>: tyypitetty virheenkäsittely ilman poikkeuksia”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Kotlin Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Either<L, R>: tyypitetty virheenkäsittely ilman poikkeuksia”?

Käyttäkää Either-tyyppiä onnistumisen ja epäonnistumisen esittämiseen ilman poikkeusten heittämistä. Harjoittelet Kotlin Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Kotlin Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Kotlin Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 1/4.

Kuinka kauan ”Either<L, R>: tyypitetty virheenkäsittely ilman poikkeuksia”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Kotlin Academy-oppitunnilla?

Kyllä. Jokainen Kotlin Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Either : tyypitetty virheenkäsittely ilman poikkeuksia
  2. Arrow Raise DSL: tyypitettyjen virheiden yhdistäminen
  3. Option ja nullable: milloin kumpaakin käytetään
  4. Toiminnallinen domain-mallinnus Arrowin ydintyypeillä
← Takaisin: Kotlin Academy