Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

!2 ● ོؔٛ ● !UBLBTFL ● 'J/$5FDIOPMPHJFT ● $MJFOU&OHJOFFS J045FBN ࣗݾ঺հ

Slide 3

Slide 3 text

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

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

ΞϓϦΫϥΠΞϯτͷઃܭΛ
 ἧ͑Δඞཁ͕͋Δ

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

Clean Architecture + MVVM

Slide 13

Slide 13 text

MVVM (Model - View - ViewModel)

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

!17 MVVMͷݕ౼ ● "OESPJE"SDIJUFDUVSF$PNQPOFOUTͰ͸-JWF%BUB5
 7JFXͷϥΠϑαΠΫϧʢը໘ճసͳͲʣʹ൥Θ͞ΕͣʹΠϯελϯεͷੜଘ؅ཧ͕Մೳʹ ● J04Ͱ͸ඪ४ͷόΠϯσΟϯάϥΠϒϥϦ͸ͳ͍
 σϑΝΫτελϯμʔυ͸3Y4XJGU ΦϒβʔόಉظʢόΠϯσΟϯάϥΠϒϥϦΛ׆༻ʣ

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

MVVM

Slide 21

Slide 21 text

Clean Architecture + MVVM

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

!26 one more thing Resource ܕ

Slide 27

Slide 27 text

!27 Resource ܕ ● JO1SPHSFTT %PVCMF ● TVDDFTT 5 ● GBJMVSF & ඇಉظʹऔಘ͞ΕΔϦιʔεͷঢ়ଶΛɺ໢ཏੑΛ΋ͬͯදݱ͍ͨ͠ ໢ཏੑ͕͋Δ ʹ ύλʔϯϚονͰ͖Δ

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

!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) } } ύλʔϯϚον͠΍ͯ͘͢ྑ͍Ͷ

Slide 30

Slide 30 text

!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Ͱى͜Γ͏ΔΤϥʔʯ͸ίϯςΩετ͕ҧ͏ ● ໢ཏతʹදݱɾϋϯυϦϯά͍ͨ͜͠ͱ͕ଟ͍ ● ʮΤϥʔʹͳΒͳ͍ʯ͜ͱ΋ࣔͤΔ

Slide 31

Slide 31 text

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

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

!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. େମ͍͚Δ͚Ͳɺ೉͍͠෦෼͸͋Δ

Slide 35

Slide 35 text

!35 Q. ΞϓϦશମΛἧ͖͑ͬͨͷʁ ● طଘίʔυ·ͰҰؾʹ߹ΘͤΔ͜ͱ͸Ͱ͖ͳ͍ ● ίʔυϕʔε͕ҧ͏ͷͰɺϦϑΝΫλͳͲΛ͖͔͚ͬʹࠩҟ͸ग़Δ ● ઃܭ͸઴ਐతʹਐԽͤ͞Δ΂͖ ● Կ͕ʮ࠷৽ͷਖ਼ղʯ͔ݟ͑ʹ͍͘ͱ͍͏໰୊ʹ޲͖߹͏ ● υΩϡϝϯςʔγϣϯͰରԠ͠Α͏ͱ͢Δͱ
 ϓϩμΫτίʔυ͔Βဃ཭͠΍͍͢ ● ϛχϚϜͳઃܭύλʔϯΛఏࣔͰ͖ΔΑ͏ɺ
 αϯϓϧϓϩδΣΫτΛ੔͑Δ A. ͖ͬͱӬԕʹWIP

Slide 36

Slide 36 text

!36 Q. ΞʔΩςΫνϟΛἧ͑ͯྑ͔ͬͨ఺͸ʁ ● 6*ʹҾ͖ͣΒΕͣʹ
 ʮυϝΠϯ͸Կ͔ʯΛத৺ͱͨٞ͠࿦͕͠΍͍͢ ● ࢓༷ͷߟྀ࿙Εɾઃܭͷѱ͞ʹؾ෇͚Δ ● ࣮࣭ϖΞϓϩ ● ࡉ͔͍ઃܭʹࠩҟ͕ग़͏Δ໰୊ʹରͯ͠͸ɺ
 ׬શΛٻΊΔ΂͖Ͱ͸ͳ͍͕ɺ
 ίϯςΩετΛ҆ఆͤ͞Δ౒ྗ͸େ੾ A. ୈҰʹ͸ɺυϝΠϯ΁ͷҙ͕ࣝڧ·ͬͨ͜ͱ

Slide 37

Slide 37 text

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

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

!39 Q. Kotlin/NativeͬͯͲ͏ͳͷʁ ● 4XJGUඇαϙʔτ ● ,PUMJO0CK$4XJGUͷม׵͸Ͱ͖Δ͚Ͳɺ
 ಛʹTUSVDU΍୅਺తσʔλܕ͕࢖͑ͳ͍ͷ͸ݫ͍͠ ● .PEFM૚ͷόΠφϦαΠζ͕ංେԽ͢Δʢ༧ײʣ ● 7JFX૚Ͱ3Y4XJGU .PEFM૚Ͱ3Y+BWBΛೖΕΔΈ͍ͨͳʜ ● .PEFM૚΋ͳΔ΂͘ϓϨʔϯʹߏ੒͢Δ͜ͱΛҙࣝ ● ,PUMJOɺ4XJGUͰɺͲͪΒͰ΋BTZODBXBJU͕
 ࢖͑ΔੈքʹͳͬͨΒݟ͑Δ΋ͷ͕มΘ͖ͬͯͦ͏ A. কདྷʹظ଴

Slide 40

Slide 40 text

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

Slide 41

Slide 41 text

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

Slide 42

Slide 42 text

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