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

FiNCのクライアントアーキテクチャを揃える試み / 20190110 #app_mp

takasek
January 10, 2019

FiNCのクライアントアーキテクチャを揃える試み / 20190110 #app_mp

【増枠】App Client Melting Pot #1「設計」 - connpass
https://app-client-mp.connpass.com/event/112973/
での発表資料です。

# 参考リンク

PEAKS(ピークス)|関 義隆, 松館 大輝, 史 翔新, 田中 賢治, 鈴木 大貴, 杉上 洋平 - iOSの設計パターンを入門から徹底解説「iOSアプリ設計パターン入門」執筆プロジェクト!
https://peaks.cc/iOS_architecture

マイクロサービスとクライアント: 
理想と現実の狭間で / Ideal and Reality of microservices from the client-side - Speaker Deck
https://speakerdeck.com/qsona/ideal-and-reality-of-microservices-from-the-client-side

10分で振り返るソフトウェアアーキテクチャの歴史2017 - Speaker Deck
https://speakerdeck.com/takasek/10fen-tezhen-rifan-rusohutoueaakitekutiyafalseli-shi-2017

アプリのアーキテクチャ ガイド  |  Android Developers
https://developer.android.com/jetpack/docs/guide#addendum

conference-app-2018/Result.kt at master · DroidKaigi/conference-app-2018
https://github.com/DroidKaigi/conference-app-2018/blob/master/app/src/main/java/io/github/droidkaigi/confsched2018/presentation/Result.kt

Result V.S. Result - Speaker Deck
https://speakerdeck.com/inamiy/result-v-dot-s-result-t-e

マイクロサービスとクライアントとコンテキスト境界 / 20181030 #microserv - Speaker Deck
https://speakerdeck.com/takasek/20181030-number-microserv

実践、BFF ~ BFFはFiNCのアプリで何を解決したのか ~ - Speaker Deck
https://speakerdeck.com/kensukeizumi/shi-jian-bff-bffhafincfalseapuridehe-wojie-jue-sitafalseka

takasek

January 10, 2019
Tweet

More Decks by takasek

Other Decks in Programming

Transcript

  1. FiNCͷ
    ΫϥΠΞϯτΞʔΩςΫνϟΛ
    ἧ͑ΔࢼΈ
    For App Client Melting Pot #1
    2019/1/10
    FiNC Technologies Inc. / iOS Development Team
    ؔ ོٛ(takasek)

    View full-size slide

  2. !2
    ● ོؔٛ
    ● !UBLBTFL
    ● 'J/$5FDIOPMPHJFT
    ● $MJFOU&OHJOFFS J045FBN

    ࣗݾ঺հ

    View full-size slide

  3. !3
    ● ʮJ04ΞϓϦઃܭύλʔϯೖ໳ʯ ڞஶ

    ● 1&",4ΑΓɺۙ೔Ұൠൃച։࢝ʂ
    IUUQTQFBLTDDJ04@BSDIJUFDUVSF
    .7$ .71 .77. 'MVY 3FEVY $MFBO"SDIJUFDUVSF
    ϞόΠϧಛ༗ͷىಈܦ࿏ɾը໘ભҠͷ੔ཧ·Ͱ໢ཏʂ
    ؔ͸ɺʮઃܭͱ͸Կ͔ʯͱ͍͏େ͖ͳओޠͰষ΄Ͳʂ
    ೥ .7$
    ʙ͔Β࿈໖ͱଓ͘
    ΞʔΩςΫνϟύλʔϯͷྺ࢙ͷ੔ཧʂ
    ϚαΧϦඞࢸͷϏοάΠγϡʔʹՌ׶ʹ௅Έ·ͨ͠ʂ
    એ఻

    View full-size slide

  4. FiNCͷ։ൃମ੍ɾαʔϏεߏ੒
    1

    View full-size slide

  5. !5
    FiNCͷ։ൃମ੍ɾαʔϏεߏ੒
    ● J04 "OESPJEฒߦ։ൃ
    ● Ϣʔβʔछผɺϓϥϯ͕ଟ͍
    ● Ұൠɺ՝ۚɺ๏ਓͳͲ
    ● Ωϟϯϖʔϯ΍Πϕϯτ΋ൃੜ
    ● ͝΄͏ͼ΢ΥʔΧʔͳͲ
    Ϗδωε୯ҐͰνʔϜΛ૊Ή

    View full-size slide

  6. !6
    FiNCͷ։ൃମ੍ɾαʔϏεߏ੒
    ● ϥϯΩϯάαʔό͔ΒϥϯΩϯά৘ใΛऔಘ
    ● ίϛϡχςΟαʔό͔ΒϥϯΩϯά։࠵άϧʔϓ৘ใΛऔಘ
    ● ϥΠϑϩάαʔόʹ࠷৽ͷา਺ΛૹΔ
    Ұը໘಺Ͱଟ਺ͷଟ͘ͷαʔϏε͕࿈ܞ
    αʔόϨεϙϯεΛͦͷ··දࣔ͢Δ͚ͩͰ͸ͳ͍…ʂ

    ͨͱ͑͹า਺ϥϯΩϯάը໘Ͱ͸ɺ

    View full-size slide

  7. !7
    qsonaʮϚΠΫϩαʔϏεͱΫϥΠΞϯτ: ཧ૝ͱݱ࣮ͷڱؒͰʯ p17
    https://speakerdeck.com/qsona/ideal-and-reality-of-microservices-from-the-client-side?slide=17
    ΫϥΠΞϯτʹϚΠΫϩαʔϏεͷϋϒ

    View full-size slide

  8. ΞϓϦΫϥΠΞϯτͷઃܭΛ

    ἧ͑Δඞཁ͕͋Δ

    View full-size slide

  9. !9
    ຊ౰ʹἧ͑Δඞཁ͕͋Δ͔ʁ
    ● ฒ΂ͯΞϓϦΛૢ࡞͢ΔౕͳΜ͍ͯͳ͍
    ● ׬શʹϢʔβʔମݧΛଗ͑Δඞཁ͸ͳ͍
    ● ͔͠͠ಉ͡ΞϓϦͳͷͰʮ࣮ݱ͍ͨ͜͠ͱʯ͸มΘΒͳ͍͜ͱ͕ଟ͍
    ● ϓϥϯɺΩϟϯϖʔϯɺ֎෦࿈ܞFUD
    ● ϓϥοτϑΥʔϜʹΑͬͯཧ༝ͳ͘ڍಈ͕ҧ͏͜ͱ͸ආ͚͍ͨ
    →ϝϦοτ্͕ճΓͦ͏

    View full-size slide

  10. !10
    ٕज़ཁ݅ͷݕ౼
    ● ڧ͍੩తܕ෇͚ݴޠʢ,PUMJO 4XJGUʣ
    ● OVMM҆શ
    ● ୅਺తσʔλܕʢTFBMFEDMBTT FOVNʣ
    ● 3Y$PNNVOJUZ
    ● 3FBDUJWF&YUFOTJPO
    →͍͚ͦ͏

    View full-size slide

  11. FiNCΫϥΠΞϯτʹదͨ͠
    ΞʔΩςΫνϟͷݕ౼
    2

    View full-size slide

  12. Clean Architecture + MVVM

    View full-size slide

  13. MVVM
    (Model - View - ViewModel)

    View full-size slide

  14. !14
    MVVM (Model-View-ViewModel)
    …ͷલʹɺ
    Presentation Domain Separation
    ʹ͍ͭͯઆ໌

    View full-size slide

  15. !15
    Presentation Domain Separation
    ● )VNBO*OUFSGBDF(VJEFMJOFTWT.BUFSJBM%FTJHO
    ● QVTI NPEBMͰ؅ཧ͞ΕͨભҠߏ଄WTDPOUFYUͰ؅ཧ͞Εͨ"DUJWJUZ
    ● 6*5BCMF7JFXWT3FDZDMFS7JFX
    ● FUD
    ϓϥοτϑΥʔϜʹΑͬͯઃܭࢥ૝ɾϑϨʔϜϫʔΫ͸େ͖͘ҟͳΔ
    ͔͠͠Model͸มΘΒͳ͍
    ɹɹ˞ Model ͱ͸ʮσʔλߏ଄Λ͋ΒΘ͢ΦϒδΣΫτʯͰ͸ͳ͍ɻ
    ɹɹɹʮViewʹؔΘΒͳ͍஌ࣝʯ͢΂ͯͷ͜ͱɻ

    View full-size slide

  16. !16
    MVVM (Model-View-ViewModel)
    ʮiOSΞϓϦઃܭύλʔϯೖ໳ʯୈ7ষΑΓ

    View full-size slide

  17. !17
    MVVMͷݕ౼
    ● "OESPJE"SDIJUFDUVSF$PNQPOFOUTͰ͸-JWF%BUB5

    7JFXͷϥΠϑαΠΫϧʢը໘ճసͳͲʣʹ൥Θ͞ΕͣʹΠϯελϯεͷੜଘ؅ཧ͕Մೳʹ
    ● J04Ͱ͸ඪ४ͷόΠϯσΟϯάϥΠϒϥϦ͸ͳ͍

    σϑΝΫτελϯμʔυ͸3Y4XJGU
    ΦϒβʔόಉظʢόΠϯσΟϯάϥΠϒϥϦΛ׆༻ʣ

    View full-size slide

  18. !18
    MVVMͷݕ౼
    ● .PEFMͰ΋ඇಉظॲཧ͕ى͜Γ͏Δ͠ɺೖྗͱग़ྗͷؔ܎͸OOʹͳΔ
    ● ίϚϯυΫΤϦ෼཭ݪଇʢ$24ʣ
    ● ίϚϯυʢ෭࡞༻Λ൐͏ʣ͸౤͛Δ͚ͩ
    ● ΫΤϦʢ෭࡞༻Λ൐Θͳ͍ʣ͸݁ՌΛड͚औΔ͚ͩ
    ● .PEFM͔Βड͚औΔ݁Ռ΋0CTFSWBCMF ετϦʔϜ
    Ͱදݱ͍ͨ͠
    AndroidͰ͸ɺLiveData͕͋Ε͹ผϥΠϒϥϦෆཁʁ
    NO!
    → ͲͪΒͷϓϥοτϑΥʔϜͰ΋ϦΞΫςΟϒϥΠϒϥϦ͕ཉ͍͠

    View full-size slide

  19. !19
    MVVMͷݕ౼
    MVVM
    with
    RxJava ❤ RxSwift
    RxͰἧ͑Ε͹ɺ྆ϓϥοτϑΥʔϜͷPR͕ޓ͍ʹಡΊΔͧ…ʂ

    View full-size slide

  20. Clean Architecture + MVVM

    View full-size slide

  21. Clean Architecture + MVVM
    ɹɹɹɹɹɹ↑
    ɹɹɹɹɹɹɹʮ+ʯͱ͸ʁ

    View full-size slide

  22. !23
    takasekʮ10෼ͰৼΓฦΔιϑτ΢ΣΞΞʔΩςΫνϟͷྺ࢙2017ʯ p5
    https://speakerdeck.com/takasek/10fen-tezhen-rifan-rusohutoueaakitekutiyafalseli-shi-2017?slide=5
    2छྨͷΞʔΩςΫνϟ

    View full-size slide

  23. !24
    Clean Architectureͷݕ౼
    MVVMʹΑͬͯPresentation Domain SeparationͰ͖ͨ…͜ΕͰສࣄղܾʁ
    NO!
    → Model಺ʹ΋ɺෳ਺ͷ৘ใΛద੾ʹऔΓ·ͱΊΔϨΠϠ͕ඞཁ
    ● αʔϏεಛੑͱͯ͠ɺ

    .PEFM΋ෳࡶʹͳΓ͕ͪ

    View full-size slide

  24. !25
    Clean Architecture
    ʮiOSΞϓϦઃܭύλʔϯೖ໳ʯୈ10ষΑΓ
    ֎→಺ͷ
    ґଘΛकΓ
    ςετɾ
    ࠶ར༻Մೳʹ

    View full-size slide

  25. !26
    one more thing
    Resource ܕ

    View full-size slide

  26. !27
    Resource ܕ
    ● JO1SPHSFTT %PVCMF

    ● TVDDFTT 5

    ● GBJMVSF &

    ඇಉظʹऔಘ͞ΕΔϦιʔεͷঢ়ଶΛɺ໢ཏੑΛ΋ͬͯදݱ͍ͨ͠
    ໢ཏੑ͕͋Δ ʹ ύλʔϯϚονͰ͖Δ

    View full-size slide

  27. !28
    Resource ܕ
    ݩωλ(1): Android Jetpack

    https://developer.android.com/jetpack/docs/guide#addendum
    //a generic class that describes a data with a status
    public class Resource {
    @NonNull public final Status status;
    @Nullable public final T data;
    @Nullable public final String message;
    private Resource(@NonNull Status status, @Nullable T data, @Nullable String message) {
    this.status = status;
    this.data = data;
    this.message = message;
    }
    public static Resource success(@NonNull T data) {
    return new Resource<>(SUCCESS, data, null);
    }
    public static Resource error(String msg, @Nullable T data) {
    return new Resource<>(ERROR, data, msg);
    }
    public static Resource loading(@Nullable T data) {
    return new Resource<>(LOADING, data, null);
    }
    }

    View full-size slide

  28. !29
    Resource ܕ
    ݩωλ(2): DroidKaigi/conference-app-2018

    https://github.com/DroidKaigi/conference-app-2018/blob/master/app/src/main/java/io/github/droidkaigi/confsched2018/presentation/Result.kt
    sealed class Result(val inProgress: Boolean) {
    class InProgress : Result(true) {
    override fun equals(other: Any?): Boolean {
    if (this === other) return true
    if (javaClass != other?.javaClass) return false
    return true
    }
    override fun hashCode(): Int = javaClass.hashCode()
    }
    data class Success(var data: T) : Result(false)
    data class Failure(val errorMessage: String?, val e: Throwable) : Result(false)
    companion object {
    fun inProgress(): Result = InProgress()
    fun success(data: T): Result = Success(data)
    fun failure(errorMessage: String, e: Throwable): Result = Failure(errorMessage, e)
    }
    }
    ύλʔϯϚον͠΍ͯ͘͢ྑ͍Ͷ

    View full-size slide

  29. !30
    Resource ͔ Resource ͔
    inamiyʮResult V.S. Resultʯ p7, 11 https://speakerdeck.com/inamiy/result-v-dot-s-result-t-e
    ● ʮ͋Δ6TF$BTFͰى͜Γ͏ΔΤϥʔʯ

    ʮ͋Δ7JFX.PEFMͰى͜Γ͏ΔΤϥʔʯ͸ίϯςΩετ͕ҧ͏
    ● ໢ཏతʹදݱɾϋϯυϦϯά͍ͨ͜͠ͱ͕ଟ͍
    ● ʮΤϥʔʹͳΒͳ͍ʯ͜ͱ΋ࣔͤΔ

    View full-size slide

  30. !31
    Resource.InProgress
    ● ΞοϓϩʔυλεΫͳͲ΋ಉ͡3FTPVSDFܕͰදݱՄೳͰخ͍͠
    ● ਐ௙͕ඞཁͳ͍৔߹͸஋Λແࢹ͢Ε͹͍͍͚ͩͳͷͰࠔΒͳ͍
    progress͸ਐḿ৘ใ(0.0ʙ1.0)Λ࣋ͭΑ͏ʹ

    View full-size slide

  31. !32
    Resource × Rx Ͱ͞Βʹศརʹ
    extension Resource: ReactiveCompatible {}
    public enum ResourceTriggerSwitchingStrategy { case useFormer, useLatter }
    extension Reactive {
    public static func from(
    trigger: Trigger,
    then execute: @escaping (Trigger.E) -> Single,
    switchingStrategy: ResourceTriggerSwitchingStrategy
    ) -> Observable>
    where Base == Resource {
    let transform: (Trigger.E) -> Observable> = { arg in
    return execute(arg)
    .asObservable()
    .map { .success($0) }
    .catchError { .just(.failure($0 as! E)) }
    .startWith(.inProgress(0))
    }
    switch switchingStrategy {
    case .useFormer: return trigger.flatMapFirst(transform).share()
    case .useLatter: return trigger.flatMapLatest(transform).share()
    }
    }
    }

    View full-size slide

  32. ΞʔΩςΫνϟΛἧ͑ΔࢼΈ ͷ࣮ࡍͷͱ͜Ζ
    3

    View full-size slide

  33. !34
    Q. ຊ౰ʹiOS/AndroidΛἧ͑ΒΕͨͷʁ
    ● 4XJGUͱ,PUMJO͸΍ͬͺΓҧ͏
    ● 4XJGUͰ͸δΣωϦοΫͳJOUFSGBDF͕࢖͑ͳ͍
    ● FOVN͸TFBMFEDMBTTͱҧ͍ɺ֤έʔεΛܕϨϕϧͰ۠ผ͠ͳ͍
    ● QBDLBHFͷཻ౓͕ҧ͍ʢ,PUMJO͸σΟϨΫτϦ୯Ґʣɺ໋໊ʹӨڹ
    ● 3Y4XJGUͱ3Y+BWB͸ҙ֎ͱҧ͏
    ● *0εϨουपΓɺ1SPDFTTPS 'MPXBCMF CBDLQSFTTVSF
    ● ΠϯελϯεͷϥΠϑαΠΫϧ
    ● TVCTDSJCF EJTQPTFͷڍಈ
    ● ࢀরΧ΢ϯτWTΨϕʔδίϨΫγϣϯ
    ● ΦϖϨʔλͷ໊લ΋ࢥͬͨΑΓଗͬͯͳ͍
    ● ࠩ෼ߋ৽Λલఏʹ͢Δ͔Ͳ͏͔Ͱߟ͑ํ͕มΘΔ
    ● "OESPJEʹ͸4VQQPSU-JCSBSZͰ௥Ճ͞Εͨ%JGG6UJM͕͋Δ
    ● J04͸σϑΝΫτελϯμʔυ͕ͳ͍
    A. େମ͍͚Δ͚Ͳɺ೉͍͠෦෼͸͋Δ

    View full-size slide

  34. !35
    Q. ΞϓϦશମΛἧ͖͑ͬͨͷʁ
    ● طଘίʔυ·ͰҰؾʹ߹ΘͤΔ͜ͱ͸Ͱ͖ͳ͍
    ● ίʔυϕʔε͕ҧ͏ͷͰɺϦϑΝΫλͳͲΛ͖͔͚ͬʹࠩҟ͸ग़Δ
    ● ઃܭ͸઴ਐతʹਐԽͤ͞Δ΂͖
    ● Կ͕ʮ࠷৽ͷਖ਼ղʯ͔ݟ͑ʹ͍͘ͱ͍͏໰୊ʹ޲͖߹͏
    ● υΩϡϝϯςʔγϣϯͰରԠ͠Α͏ͱ͢Δͱ

    ϓϩμΫτίʔυ͔Βဃ཭͠΍͍͢
    ● ϛχϚϜͳઃܭύλʔϯΛఏࣔͰ͖ΔΑ͏ɺ

    αϯϓϧϓϩδΣΫτΛ੔͑Δ
    A. ͖ͬͱӬԕʹWIP

    View full-size slide

  35. !36
    Q. ΞʔΩςΫνϟΛἧ͑ͯྑ͔ͬͨ఺͸ʁ
    ● 6*ʹҾ͖ͣΒΕͣʹ

    ʮυϝΠϯ͸Կ͔ʯΛத৺ͱͨٞ͠࿦͕͠΍͍͢
    ● ࢓༷ͷߟྀ࿙Εɾઃܭͷѱ͞ʹؾ෇͚Δ
    ● ࣮࣭ϖΞϓϩ
    ● ࡉ͔͍ઃܭʹࠩҟ͕ग़͏Δ໰୊ʹରͯ͠͸ɺ

    ׬શΛٻΊΔ΂͖Ͱ͸ͳ͍͕ɺ

    ίϯςΩετΛ҆ఆͤ͞Δ౒ྗ͸େ੾
    A. ୈҰʹ͸ɺυϝΠϯ΁ͷҙ͕ࣝڧ·ͬͨ͜ͱ

    View full-size slide

  36. !37
    Q. ΞʔΩςΫνϟΛἧ͑ͯྑ͔ͬͨ఺͸ʁ
    takasekʮϚΠΫϩαʔϏεͱΫϥΠΞϯτͱίϯςΩετڥքʯ p6
    https://speakerdeck.com/takasek/20181030-number-microserv?slide=6

    View full-size slide

  37. !38
    Q. iOS/Androidͷಉ࣌։ൃͬͯඇޮ཰Ͱ͸ʁ
    ● ࣗ૸Ͱ͖Δ෦෼͸ࣗ૸ͨ͠΄͏͕Α͍͜ͱ΋͋Δ
    ● ϓϩτλΠϓϨϕϧͰ͸ยํ͕ઌߦ։ൃ
    ● ยํ͕ઌߦϦϦʔεˠϑΟʔυόοΫΛݩʹ௥Ճ։ൃ
    A. ͦΕͳ

    View full-size slide

  38. !39
    Q. Kotlin/NativeͬͯͲ͏ͳͷʁ
    ● 4XJGUඇαϙʔτ
    ● ,PUMJO0CK$4XJGUͷม׵͸Ͱ͖Δ͚Ͳɺ

    ಛʹTUSVDU΍୅਺తσʔλܕ͕࢖͑ͳ͍ͷ͸ݫ͍͠
    ● .PEFM૚ͷόΠφϦαΠζ͕ංେԽ͢Δʢ༧ײʣ
    ● 7JFX૚Ͱ3Y4XJGU .PEFM૚Ͱ3Y+BWBΛೖΕΔΈ͍ͨͳʜ
    ● .PEFM૚΋ͳΔ΂͘ϓϨʔϯʹߏ੒͢Δ͜ͱΛҙࣝ
    ● ,PUMJOɺ4XJGUͰɺͲͪΒͰ΋BTZODBXBJU͕

    ࢖͑ΔੈքʹͳͬͨΒݟ͑Δ΋ͷ͕มΘ͖ͬͯͦ͏
    A. কདྷʹظ଴

    View full-size slide

  39. !40
    Q. ϩδοΫ͸αʔόαΠυʹدͤΔ΂͖Ͱ͸ʁ
    A. Ұ֓ʹͦ͏ͱ͸͍͑ͳ͍
    takasekʮϚΠΫϩαʔϏεͱΫϥΠΞϯτͱίϯςΩετڥքʯ p23
    https://speakerdeck.com/takasek/20181030-number-microserv?slide=23

    View full-size slide

  40. !41
    Q. ϩδοΫ͸αʔόαΠυʹدͤΔ΂͖Ͱ͸ʁ
    A2. ͦͷ͏͑Ͱɺద੾ͳBFF(Backends for Frontends)͸༗ޮ
    ● ৄ͘͠͸!J[NFBMͷൃදͰ

    IUUQTTQFBLFSEFDLDPNLFOTVLFJ[VNJTIJKJBOCGGCGGIBGJODGBMTFBQVSJEFIFXPKJFKVFTJUBGBMTFLB
    ● %SPJE,BJHJ !RTPOB
    ΋ָ͓͠Έʹ

    View full-size slide

  41. !42
    FiNC Technologies͸ࠓޙ΋ݚڀ͍͖ͯ͠·͢ʂ

    View full-size slide