Upgrade to Pro — share decks privately, control downloads, hide ads and more …

kotlin-resultを用いて鉄道志向なエラーハンドリングを試みる

 kotlin-resultを用いて鉄道志向なエラーハンドリングを試みる

ca.aab #2

Yoshikane Fumitaka

March 16, 2023
Tweet

More Decks by Yoshikane Fumitaka

Other Decks in Programming

Transcript

  1. GO BEYOND TOGETHER
    Chief Creative Officer BABY NAIL EXILE EXILE THE SECOND 三代目 J SOUL BROTHERS from EXILE TRIBE GENERATIONS from EXILE TRIBE THE RAMPAGE FANTASTICS

    from EXILE TRIBE BALLISTIK BOYZ from EXILE TRIBE 劇団EXILE DEEP SQUAD DOBERMAN INFINITY Dream Ami Dream Shizuka Happiness 伶 PKCZ DJ DARUMA m-flo

    MIYAVI Crystal Kay JAY’ED Leola MABU Girls² iScream Lucky² PSYCHIC FEVER ACTOR MODEL ATHLETE AMAZING COFFEE
    kotlin-resultを用いて

    鉄道志向なエラーハンドリングを
    試みる
    Yoshikane Fumitaka, @black_bracken
    CA.aab #2

    View Slide

  2. GO BEYOND TOGETHER
    自己紹介
    R 吉兼 史崇 (わらびF
    R @black_bracke5
    R CL事業本部でAndroi#
    R 最近はGlanceでウィジェットを書いています

    View Slide

  3. GO BEYOND TOGETHER
    agenda
    Kotlin標準ライブラリのResult

    michaelbull/kotlin-result

    鉄道志向プログラミング(ROP)とは

    bindingを使った構文糖

    技術の選定と注意点

    View Slide

  4. GO BEYOND TOGETHER
    Kotlin標準ライブラリのResultのおさらい
    ˆ 例外をキャプチャし、成功or失敗したことを1クラスで値として表現すx
    ˆ Result = T | Throwablr
    ˆ エラー側の型をジェネリクスで持たなu
    ˆ (Androidなどに限らない) Kotlinに向けた、成功と失敗のいずれかの型として有–
    ˆ kotlinx.coroutinesのContinuation#resumeWithなどで利用されていx
    ˆ sealed classではない (1.7 時点; Result.Failureをvalueに入れたvalue class‘
    ˆ onSuccess, onFailureなどのメソッドを使う前8
    ˆ ドメイン固有のエラー状態を表現する必要があるなら、Resultの代わりに独
    自にsealed classで定義することが推奨されている

    View Slide

  5. GO BEYOND TOGETHER
    michaelbull/kotlin-result
    V Result型を提供するライブラリ (Eitherh
    V エラー側の型を持g
    V OkもしくはErr型 (sealedh
    V 標準のResultと同様のメソッドを持g
    V 加えてflatMapを持g
    V エラー型の上限に制約がなq
    V Exceptionに制限されなq
    V bindingという機x
    V 後述

    View Slide

  6. GO BEYOND TOGETHER
    agenda
    Kotlin標準ライブラリのResult

    michaelbull/kotlin-result

    鉄道志向プログラミング(ROP)とは

    bindingを使った構文糖

    技術の選定と注意点

    View Slide

  7. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    s 正常処理に主軸を置いたエラーハンドリングへのアプローq
    s 関数型プログラミングの一部を簡単に砕いたもp
    s 複数のエラー状態も型を保R
    s Scott Wlaschinが提
    s Domain Modeling Made Functionalの著者
    s 正常な処理に主軸を置くとž
    s 手続き的な記述では、各処理毎に問題があればそれぞれエラーハン
    ドリングを行い、早期リターンや例外の送出を行²
    s ロジックを正常なルート(= happy path)に集中して記述することで
    可読性を高められないだろうか?

    View Slide

  8. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    t 簡単のために以下のような具体例(ユースケース)を考えw
    ur 現在のユーザを取得し認可されているか確b
    –r ユーザーIDをもとにデータを取e
    Dr 取得したデータを保d
    vr 取得したデータを返’
    t まず手続き的
    t エラーハンドリングなし

    View Slide

  9. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    @ エラーハンドリングをしていG
    @ 本質的な処理よりエラーハンドリ
    ングの方が多い
    エラーハンドリンr
    @ (re) throi
    @ retura
    @ etc

    View Slide

  10. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    User#isAuthorized()
    SampleUsecase#invoke()
    on success
    on failure
    RemoteRepository#fetchInfo() LocalRepository#save()
    Output
    Input
    手続き的

    View Slide

  11. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    User#isAuthorized()
    SampleUsecase#invoke()
    on success
    on failure
    RemoteRepository#fetchInfo() LocalRepository#save()
    Output
    Input
    User#isAuthorized()
    SampleUsecase#invoke()
    on success
    on failure
    RemoteRepository#fetchInfo() LocalRepository#save()
    Output
    Input
    手続き的
    鉄道志向
    エラーが起きても連結できれば良い

    View Slide

  12. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    D 前提: 関数合成についG
    D 複数の関数を組み合わせることで新たな1つの関数に合成する
    function1(apple): Banana function2(banana): Cherry

    View Slide

  13. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    D 前提: 関数合成についG
    D 複数の関数を組み合わせることで新たな1つの関数に合成する

    View Slide

  14. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    D 前提: 関数合成についG
    D 複数の関数を組み合わせることで新たな1つの関数に合成する
    fun newFunction(apple): Cherry = function2(function1(apple))

    View Slide

  15. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    p 各メソッドがResultを返すようにすれば、それらを合成して1つのユースケースに出来そ™
    p 関数の連結になるので、正常なルート(=処理の実態)に集中して記述でき–
    p エラーが発生しても、型から分かるのでバイパスするような形にすればO8
    p そのユースケースもResultで返してあとでハンドリング
    User#isAuthorized()
    SampleUsecase#invoke()
    on success
    on failure
    RemoteRepository#fetchInfo() LocalRepository#save()
    Output
    Input

    View Slide

  16. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    i 実際にこれに合わせてプログラムを書いてみI
    i 残念ながらコンパイルは通らなƒ
    i fetchInfoはUserIdを受け取るのであって、Resultを受け取る訳ではなƒ
    i 変換も出来ない

    View Slide

  17. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    i 実際にこれに合わせてプログラムを書いてみI
    i 残念ながらコンパイルは通らなƒ
    i fetchInfoはUserIdを受け取るのであって、Resultを受け取る訳ではなƒ
    i 変換も出来ない
    型が合わない

    View Slide

  18. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    ‚ 型が合わない理g
    ‚ fetchInfo()などのメソッドは、Resultを返すことで出力が2路線に対応し`
    ‚ しかし入力は1路線(正常値のみ)にしか対応していなh
    ‚ エラーを受け取り、その時には何もせずただ後ろにエラーを返したh
    ‚ しかしメソッドすべてが引数にResultを受け取るのは非現実的では?
    この路線に対応する必要がある
    Result Result Result
    T

    View Slide

  19. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    もし正常な値なら

     その値をもう1段ネストした形に変形して潰して返す
    もし異常な値なら

     何もせずそのまま返す
    もし異常な値なら

     何もせずそのまま返す
    ...ようなメソッドがResultにあれば対応可能
    Result.func(f: (T) -> Result): Result

    View Slide

  20. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    G ListのflatMapが同じような機能を持ってい‚
    G map: (T) -> Rを受け取り、ListをListに変w
    G 空なら何もしなR
    G flatten: List>をListに変w
    G flatMap: (T) -> Listを受け取り、ListをListに変換

    View Slide

  21. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    G ListのflatMapが同じような機能を持ってい‚
    G map: (T) -> Rを受け取り、ListをListに変w
    G 空なら何もしなR
    G flatten: List>をListに変w
    G flatMap: (T) -> Listを受け取り、ListをListに変換

    G Resultにもありまp
    G map: (T) -> Rを受け取り、ResultをResultに変w
    G flatMap: (T) -> Resultを受け取り、Resultを
    Resultに変換
    G flatMaœ
    G 入れ子構造に変換して、変換後に潰p
    G Listであれば空なら何もしなR
    G ResultであればOk型でなければ何もしなR
    G (...monadic!)

    View Slide

  22. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    User#isAuthorized()
    SampleUsecase#invoke()
    on success
    on failure
    RemoteRepository#fetchInfo() LocalRepository#save()
    Output
    Input

    View Slide

  23. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    5

    View Slide

  24. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    5

    View Slide

  25. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    f エラー型につい™
    f 今回は例のために文字列にしてい`
    f 実際はドメイン固有なエラーを表現出来たほうが良r
    f sealed interfaceでUsecase/Repository等にそのエラーを定y
    f mapEitherなどを使ってレイヤー毎にエラー型の変換を行i
    f やり過ぎると無意味なボイラープレートになる

    View Slide

  26. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    g 実装とエラーハンドリングをより分離するアプロー‘
    g 成功と失敗のレールで処理を連結すy
    g flatMapでResultの結果を連結して関数を合成すy
    g エラーの種類も型を保ったまま伝播すy
    g Androidでの適用範囲
    g (← Usecase) ← Repository ← DataSource

    View Slide

  27. GO BEYOND TOGETHER
    agenda
    Kotlin標準ライブラリのResult

    michaelbull/kotlin-result

    鉄道志向プログラミング(ROP)とは

    bindingを使った構文糖

    技術の選定と注意点

    View Slide

  28. GO BEYOND TOGETHER
    鉄道志向 (Railway Oriented Programming)
    6 省略

    View Slide

  29. GO BEYOND TOGETHER
    技術の選定と注意点
    m 鉄道指向プログラミングの採用についx
    m Kotlinのエラーハンドリングにおける銀の弾丸ではな’
    m KEEPでは、標準ライブラリとしてROPは採用しな’
    m 不必要なケースで使うとそれは例外の再発明にな2
    m 想定できないエラーは例外で扱G
    m エラーの内容が本当に利用する時に必要か考えるこu
    m 各エラー毎にドメインモデル(sealed class)が必要かf
    m 目的と手段を履き違えないよう

    View Slide

  30. GO BEYOND TOGETHER
    技術の選定と注意点
    d CLで跋扈するデータ型た`
    d Arrow-kR
    d Try (removed in latest$
    d Optio%
    d Kotlin-stdli#
    d Result
    d ライブラリの選定は慎重l
    d 用途に対して適切e
    d 特にデータレイヤ(~=ドメイン層)など
    でも使われる場v
    d 自前で定義しても良i
    d KMMへの移行に合わせて排除

    View Slide

  31. LIVE CAST ONDEMAND PROGRAM LIVE STREAMING COMMUNITY
    ありがとうございました
    V 参考資d
    V https://github.com/Kotlin/KEEP/blob/master/proposals/stdlib/result.m4
    V https://github.com/michaelbull/kotlin-resulg
    V https://github.com/swlaschin/RailwayOrientedProgramminT
    V https://fsharpforfunandprofit.com/ropX
    V https://fsharpforfunandprofit.com/posts/recipe-part2X
    V https://fsharpforfunandprofit.com/posts/against-railway-oriented-programming/

    View Slide