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

Either で想定内のエラーと想定外のエラーを別ものにしたい!

Either で想定内のエラーと想定外のエラーを別ものにしたい!

Rx Ja Night Vol.2 (https://connpass.com/event/57150/)

Ryutaro Miyashita

June 12, 2017
Tweet

More Decks by Ryutaro Miyashita

Other Decks in Technology

Transcript

  1. &JUIFSד

    䟝㹀ⰻךؒٓ٦ה

    䟝㹀㢩ךؒٓ٦׾

    ⴽ׮ךח׃׋ְ
    3Y+B/JHIU7PM

    View Slide

  2. 㹧♴畆㣐龤
    $IBU8PSL吳䒭⠓爡
    ،فٔ؛٦ءّٝꟚ涪鿇ث٦ئ٦ت٦
    [email protected]

    View Slide

  3. ⹛堣
    䟝㹀ⰻך㣟侁䟝㹀㢩ך㣟侁׾ⴓֽ׋ְ
    䟝㹀ⰻ
    8FC"1*ؙٔؒأزָة؎ي،ؐز׃׋
    䟝㹀㢩
    ءأذيך㉏겗זו

    View Slide

  4. 3Y+BWBךؒٓ٦عٝسؚٔٝ
    0CTFSWBCMFPO&SSPS
    'MPXBCMFPO&SSPS
    4JOHMFPO&SSPS
    $PNQMFUBCMFPO&SSPS
    .BZCFPO&SSPS
    ؒٓ٦ך「ֽ《׶⯓כא

    View Slide


  5. ؙٔحؙ̔ؿ؋؎ٕ《䖤̔،حفٗ٦س
    RxBinding.clicks(button)
    .map { /* Get file */ }
    .flatMap { /* Upload */ }
    ~~~~~
    .subscribe({
    /* Success */
    }, {
    /* IOException or Request failure */
    })

    View Slide

  6. RxBinding.clicks(button)
    .map { /* Get file */ }
    .flatMap { /* Upload */ }
    ~~~~~
    .subscribe({
    /* Success */
    }, {
    /* IOException or Request failure */
    })
    ֿֿדPO&SSPSָ鸐濼ׁ׸׷ה

    ؙٔحؙ̔ؿ؋؎ٕ《䖤̔،حفٗ٦س

    View Slide

  7. RxBinding.clicks(button)
    .map { /* Get file */ }
    .flatMap { /* Upload */ }
    ~~~~~
    .subscribe({
    /* Success */
    }, {
    /* IOException or Request failure */
    })
    4VCTDSJCFSPO&SSPSחⳢ椚ָ獳׶

    ؙٔحؙ̔ؿ؋؎ٕ《䖤̔،حفٗ٦س

    View Slide

  8. RxBinding.clicks(button)
    .map { /* Get file */ }
    .flatMap { /* Upload */ }
    ~~~~~
    .subscribe({
    /* Success */
    }, {
    /* IOException or Request failure */
    })
    ؙٔحؙ؎كٝزכ׮ֲ굲׿דֿזְ

    ؙٔحؙ̔ؿ؋؎ٕ《䖤̔،حفٗ٦س

    View Slide

  9. ؒٓ٦عٝسؚٔٝؔلٖ٦ةכ葿ղ֮׷
    PO&SSPS3FUVSO
    PO&SSPS3FTVNF/FYU
    SFUSZ
    SFUSZ8IFO
    ˑؒٓ٦˒׏גז׿׌׏׋׏ֽ
    3Y+BWBךؒٓ٦عٝسؚٔٝ

    View Slide

  10. ؿ؋؎ָٕ鼅䫛ׁ׸גְזְךַ
    ؿ؋؎ָٕ《䖤דֹזַ׏׋ךַ
    ،حفٗ٦س㼎韋㢩ךؿ؋؎ٕ䕎䒭׌׏׋ךַ
    8FC؟٦غ٦ָتؐٝ׃גְ׷ךַ
    ؔؿٓ؎ٝזךַ
    ˑؒٓ٦˒ה♧〡ח鎉׏ג׮˘˘
    ،فٔה׃גˑ姻׃ְ˒䮙⹛כؒٓ٦

    View Slide

  11. RxBinding.clicks(button)
    .map { /* Get file */ }
    .flatMap { /* Upload */ }
    ~~~~~
    .subscribe({
    if (it.isSuccessful) {
    /* Success */
    } else {
    /* Request failure */
    }
    }, {
    /* IOException */
    })
    PO/FYUח3FTVMU㘗׫׋ְז׮ך׾굲לׅ

    View Slide

  12. PO/FYUח
    &JUIFS׾굲לׅ

    View Slide

  13. public abstract class Either {
    public static Either left(A a) {
    new Left<>(a);
    }
    public static Either right(B b) {
    new Right<>(b);
    }
    public abstract boolean isLeft();
    public abstract boolean isRight();
    public abstract X fold(Fold l,
    Fold r);
    }
    &JUIFSKBWB

    View Slide

  14. public class Left extends Either {
    private final A a;
    public Left(A a) { this.a = a; }
    @Override
    public boolean isLeft() { return true; }
    @Override
    public boolean isRight() { return false; }
    @Override
    public X fold(Fold l, Fold r) {
    return l.fold(a);
    }
    }
    -FGUKBWB 3JHIUKBWB

    View Slide

  15. public interface FoldJ {
    Y fold(X value);
    }
    'PMEKBWB

    View Slide

  16. &JUIFS
    אך㘗ךֲ׍ծְ׆׸ַ㘗ך⦼׾䭯א
    ؟ـؙٓأה׃ג-FGU3JHIU㘗ָ֮׷
    䧭⸆כ姻׃ְ SJHIU
    חַֽג3JHIUד鵤ׅ
    㣟侁כ-FGUד鵤ׅ
    3Y+BWBדכ-FGU׾5ISPXBCMFחׅ׷ה葺ׁ׉ֲ

    View Slide

  17. fun a(): Observable>
    = Observable.create {
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.right(“Hello”))
    it.onNext(Either.right(“World”))
    it.onNext(Either.right(“Foo Bar Buzz”))
    }

    0CTFSWBCMFDSFBUF

    View Slide

  18. fun a(): Observable>
    = Observable.create {
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.right(“Hello”))
    it.onNext(Either.right(“World”))
    it.onNext(Either.right(“Foo Bar Buzz”))
    }

    0CTFSWBCMFDSFBUF
    䧭⸆儗כ4USJOH 㣟侁儗כ5ISPXBCMF׾䭯א&JUIFS

    View Slide

  19. fun a(): Observable>
    = Observable.create {
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.right(“Hello”))
    it.onNext(Either.right(“World”))
    it.onNext(Either.right(“Foo Bar Buzz”))
    }

    0CTFSWBCMFDSFBUF
    ⡦㔐ד׮㣟侁׾鵤ֿׅהָדֹ׷

    View Slide

  20. fun a(): Observable>
    = Observable.create {
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.left(RuntimeException()))
    it.onNext(Either.right(“Hello”))
    it.onNext(Either.right(“World”))
    it.onNext(Either.right(“Foo Bar Buzz”))
    }

    0CTFSWBCMFDSFBUF
    ׮׍׹׿䧭⸆׮⡦㔐ד׮鵤ֿׅהָדֹ׷

    View Slide


  21. 0CTFSWBCMFDSFBUF
    a().subscribe({ either ->
    either.fold({
    /* left, “it” is Throwable */
    }, {
    /* right, “it” is String */
    })
    }, {
    /* Error */
    })

    View Slide


  22. 0CTFSWBCMFDSFBUF
    a().subscribe({ either ->
    either.fold({
    /* left, “it” is Throwable */
    }, {
    /* right, “it” is String */
    })
    }, {
    /* Error */
    })
    4VCTDSJCFSPO/FYUך⚥ח׮ֲ媮「ֽ〡׾⡲׷
    &JUIFS" #ד䭷㹀׃׋ˑ㘗˒ד穠卓׾「ֽ《׸׷

    View Slide


  23. ,PUMJOד׮׏הأو٦زחדֹזְַז

    View Slide

  24. sealed class Either {
    abstract val isLeft: Boolean
    abstract val isRight: Boolean
    }
    &JUIFSLU

    View Slide

  25. &JUIFSLU
    data class Left(val value: A)
    : Either() {
    override val isLeft: Boolean = true
    override val isRight: Boolean = false
    }
    data class Right(val value: B)
    : Either() {
    override val isLeft: Boolean = false
    override val isRight: Boolean = true
    }

    View Slide

  26. &JUIFSLU
    inline fun Either.fold(
    left: (A) -> X,
    right: (B) -> X
    ): X = when (this) {
    is Left -> left(value)
    is Right -> right(value)
    }

    View Slide

  27. &JUIFSLU
    inline fun Either.fold(
    left: (A) -> X,
    right: (B) -> X
    ): X = when (this) {
    is Left -> left(value)
    is Right -> right(value)
    }
    ꟼ侧׾「ֽ《׏ג

    View Slide

  28. &JUIFSLU
    inline fun Either.fold(
    left: (A) -> X,
    right: (B) -> X
    ): X = when (this) {
    is Left -> left(value)
    is Right -> right(value)
    }
    XIFO䒭ד㘗ח䘔ׄג㹋遤ׅ׷ꟼ侧׾ⴖ׶剏ִ

    View Slide

  29. fun b(): Observable>
    = Observable.create {
    it.onNext(Left(RuntimeException()))
    it.onNext(Left(RuntimeException()))
    it.onNext(Left(RuntimeException()))
    it.onNext(Right(“Hello”))
    it.onNext(Right(“World”))
    it.onNext(Right(“Foo Bar Buzz”))
    }

    0CTFSWBCMFDSFBUF

    View Slide

  30. fun b(): Observable>
    = Observable.create {
    it.onNext(Left(RuntimeException()))
    it.onNext(Left(RuntimeException()))
    it.onNext(Left(RuntimeException()))
    it.onNext(Right(“Hello”))
    it.onNext(Right(“World”))
    it.onNext(Right(“Foo Bar Buzz”))
    }

    0CTFSWBCMFDSFBUF
    刿חأحؗٔ剅ֻֿהָדֹ׷

    View Slide


  31. 0CTFSWBCMFDSFBUF
    b().subscribe({ either ->
    either.fold({
    /* left, “it” is Throwable */
    }, {
    /* right, “it” is String */
    })
    }, {
    /* Error */
    })
    +BWBד㹀纏׃׋הֹה「ֽ《׶倯כずׄ

    View Slide

  32. ׁ׵ח
    typealias RxEither = Either
    typealias RxRight = Right
    typealias RxLeft = Left
    fun Observable.either():
    Observable> =
    map { RxRight(it) as RxEither }
    .onErrorReturn { RxLeft(it) }

    View Slide

  33. ׁ׵ח
    typealias RxEither = Either
    typealias RxRight = Right
    typealias RxLeft = Left
    fun Observable.either():
    Observable> =
    map { RxRight(it) as RxEither }
    .onErrorReturn { RxLeft(it) }
    -FGU㘗ָ5ISPXBCMFך㘗׾UZQFBMJBTד欽䠐

    View Slide

  34. ׁ׵ח
    typealias RxEither = Either
    typealias RxRight = Right
    typealias RxLeft = Left
    fun Observable.either():
    Observable> =
    map { RxRight(it) as RxEither }
    .onErrorReturn { RxLeft(it) }
    䭁䓸ꟼ侧ד0CTFSWBCMFFJUIFS׾欽䠐

    View Slide

  35. ׁ׵ח
    fun c(): Observable
    = Observable.create {
    it.onNext(“Hello, world”)
    it.onError(RuntimeException())
    }
    c().either().subscribe({ either ->
    either.fold({
    /* left, “it” is Throwable */
    }, {
    /* right, “it” is String */
    })
    }, {
    /* Error */
    })

    View Slide

  36. ׁ׵ח
    fun c(): Observable
    = Observable.create {
    it.onNext(“Hello, world”)
    it.onError(RuntimeException())
    }
    c().either().subscribe({ either ->
    either.fold({
    /* left, “it” is Throwable */
    }, {
    /* right, “it” is String */
    })
    }, {
    /* Error */
    })
    兛鸐ך0CTFSWBCMFָ֮׏ג׮

    View Slide

  37. ׁ׵ח
    fun c(): Observable
    = Observable.create {
    it.onNext(“Hello, world”)
    it.onError(RuntimeException())
    }
    c().either().subscribe({ either ->
    either.fold({
    /* left, “it” is Throwable */
    }, {
    /* right, “it” is String */
    })
    }, {
    /* Error */
    })
    䭁䓸ꟼ侧דFJUIFSؔلٖ٦ةך״ֲח䮶׷莸ֲ

    View Slide

  38. ׁ׵ח
    fun c(): Observable
    = Observable.create {
    it.onNext(“Hello, world”)
    it.onError(RuntimeException())
    }
    c().either().subscribe({ either ->
    either.fold({
    /* left, “it” is Throwable */
    }, {
    /* right, “it” is String */
    })
    }, {
    /* Error */
    })
    0CTFSWBCMFNFSHFזוד䕵甧א

    View Slide

  39. תה׭
    䟝㹀ⰻך㣟侁䟝㹀㢩ך㣟侁׾ⴓֽ׋ְ
    &JUIFS㘗׾⡲׏גⴓֽ׷ֿהָדֹ׷
    ؔلٖ٦ة٦דכזֻ㘗דⴓֽ׷
    ,PUMJO׾⢪ֲה刿חأو٦زח㹀纏דֹ׷
    䭁䓸ꟼ侧׾⢪׏ג傀㶷ך0CTFSWBCMF׮

    &JUIFS5ISPXBCMF 5ח㢌䳔〳腉
    &JUIFS荈⡤כ4DBMBח׮׏הؼٝزָ֮׷
    -FGU 3JHIUךNBQװTXBQזוזו

    View Slide

  40. ֶ׃תְ
    IUUQTHJUIVCDPNSZVHPP&JUIFS4BNQMF

    View Slide