DroidKaigi.collect{ #1@Tokyo }で「例外を投げるな、値を返せ」というLTをしました

書いている人 モバイルアプリケーションアーキテクト(Android)として働いています。モバイルアプリケーションのアーキテクチャ、自動テスト、CI/CDに興味があります。もっと詳しく
昨日2023年3月31日に開催されたDroidKaigi.collect{ #1@Tokyo }にて、「例外を投げるな、値を返せ」というタイトルでLTをしました。発表資料はSpeaker Deckに公開しております。
5分で話すのが大変だったので、あらかじめ早口の練習をした上で早口で話しました。
要約
発表内容の簡単な要約です。
- 例外の送出は参照透過性を壊す。また、型安全でもない。
- 例外を返す代わりに、正常・異常の直和を表現できる型を返す。
- 自分で型を作ってもいいし、
kotlin.Result<T>
やarrow.core.Either<Throwable, T>
も使える。 kotlin.Result<T>
はKotlin 1.3から導入されているので、導入しやすい。arrow.core.Either<Throwable, T>
はΛrrowという、Kotlinの関数型スタイルを強化するライブラリを導入する必要がある。arrow.core.Either<Throwable, T>
は、例外の型を書ける点がkotlin.Result<T>
よりも良い。ただ、Λrrowは大きいライブラリなので、Eitherのためだけに気軽に入れられない。- Eitherを書くのはそこまで大変でもないので、自分で書いても良い。
Resultの例
/**
* [a]を[b]で除算した結果をResultとして返す。
*
* [b]が0の場合は[ZeroDivisionException]を返す。
*/
fun divideToResult(a: Int, b: Int): Result<Int> =
if (b == 0) Result.failure(ZeroDivisionException())
else Result.success(a / b)
Eitherの例
/**
* [a]を[b]で除算した結果をEither#Rightとして返す。
*
* [b]が0の場合はEither#Leftとして[ZeroDivisionException]を返す。
*/
fun divideToEither(a: Int, b: Int): Either<DivideException, Int> =
if (b == 0) Either.Left(DivideException.ZeroDivisionException())
else Either.Right(a / b)
Right(右)とRight(正しい)の掛け言葉で、Rightが正常ケースとなるのが慣習。
References
- arrow.core.Either, retrieved from https://arrow-kt.io/docs/apidocs/arrow-core/arrow.core/-either/
- kotlin.Result, https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-result/
- Paul Chiusano, Rúnar Bjarnason, (2015), Scala関数型デザイン&プログラミング, インプレス
- Keishin Yokomaku, (2023), KotlinでEitherしたい, retrieved from https://speakerdeck.com/keithyokoma/either-in-kotlin