Slide 1

Slide 1 text

アッテ開発の技術 SwiftとRxSwift ⼤庭 慎⼀郎 株式会社メルカリ / 株式会社ソウゾウ 2016/4/18 atte FeS【Go・Swift開発編】 1

Slide 2

Slide 2 text

⾃⼰紹介 2 ⼤庭 慎⼀郎 ooba / bricklife 株式会社メルカリに2013年4⽉⼊社 現在は株式会社ソウゾウへ出向中 「メルカリ」iOS版の⽴ち上げ 「メルカリ アッテ」iOS版の⽴ち上げ

Slide 3

Slide 3 text

ϝϧΧϦΞος 3 ʮͳΜͰ΋ืूͰ͖Δ ɹ஍ҬίϛϡχςΟΞϓϦʯ iOS 8Ҏ߱ରԠ Swift 2.2Ͱઈࢍ։ൃத RxSwiftΛશ໘࠾༻

Slide 4

Slide 4 text

iOS版開発の歴史 4 できごと メンバー 2015年10⽉ ソウゾウに出向 モック作成開始 ライブラリ&設計検討開始 1 11⽉ RxSwift採⽤決定 本実装開始 合宿 1 12⽉ 幻の初サブミット 1 2016年1⽉ 孤独な⼀⼈開発から脱出 2 2⽉ 紹介制で公開 3 3⽉ 正式オープン 4 4⽉ Go Boldに開発中 4.5

Slide 5

Slide 5 text

なぜiOS 8以降か

Slide 6

Slide 6 text

なぜiOS 8以降か 6 2015年10⽉のタイミングでiOS 7のシェ アはわずか iOS 8と7とではSDKが⼤きく違う 実装スピード優先 Carthageが使いたかった

Slide 7

Slide 7 text

なぜSwiftか 7

Slide 8

Slide 8 text

なぜSwiftか 8 アッテは新規プロジェクト メルカリiOS版の資産はほぼ使えない ⻑くメンテナンスするコードになる いまSwift採⽤しないでいつ採⽤する? ⼈材募集効果も期待

Slide 9

Slide 9 text

Swiftでないとできないこと 9 型安全、Optional、enum、etc. APIKitやHimotokiなど⽇本製のイケてる ライブラリを使える • しかしAPIKitはJSON-RPC 2.0と相性が悪かったので泣 く泣く不採⽤ • 同じ思想でJSONRPCKitというのを⾃作した

Slide 10

Slide 10 text

JSONRPCKit 10 struct Like: RequestType { typealias Response = LikeResult let offerId: Int64 var method: String { return "LikeService.Like" } var params: AnyObject? { return ["offer_id": NSNumber(longLong: offerId)] } } { id: “1”, jsonrpc: “2.0", method: “LikeService.Like", params: { “offer_id”: 123456; } }

Slide 11

Slide 11 text

API側の実装 11 type LikeParams struct { OfferId int64 `json:"offer_id"` }

Slide 12

Slide 12 text

なぜRxSwiftか

Slide 13

Slide 13 text

その前に

Slide 14

Slide 14 text

なぜリアクティブ プログラミングか

Slide 15

Slide 15 text

なぜリアクティブプログラミングか 15 メルカリiOS版では、Objective-Cでリア クティブプログラミングを実現する ReactiveCocoaをヘビーに使っていた もうリアクティブプログラミングなしには プログラムが組めない!

Slide 16

Slide 16 text

リアクティブプロ グラミングとは

Slide 17

Slide 17 text

リアクティブプログラミングとは 17 変なこと⾔うとマサカリが⾶んで来るので 説明割愛

Slide 18

Slide 18 text

リアクティブプログラミングのメリット 18 様々な同期処理や⾮同期処理を 「ストリームをどう扱うか」 という視点から「統⼀的」に かつ「宣⾔的」に記述できる

Slide 19

Slide 19 text

リアクティブプログラミングが提供するもの 19 1. ストリームを⽣成する⽅法 2. ストリームを加⼯する⽅法 3. ストリームを監視する⽅法

Slide 20

Slide 20 text

これがストリームだ! 20 どちらかの発⽣によって ストリームが終わる 完了 エラー データ 時間 開始 or ↑この図を「マーブル図」という

Slide 21

Slide 21 text

ストリームの⽣成 21 ⽂字列、配列、KVO、UIイベント、ネット ワーク通信、デリゲートメソッド呼び出し、 など、なんでもストリームにできる

Slide 22

Slide 22 text

配列のストリーム化 22 [0, 1, 2, 3]

Slide 23

Slide 23 text

タップのストリーム化 23 タップ ダブルタップ タップ

Slide 24

Slide 24 text

テキスト⼊⼒のストリーム化 24 " "#$ "# "# A B C Delete

Slide 25

Slide 25 text

ネットワーク通信のストリーム化 25 ϦΫΤετ ड৴த ड৴׬ྃ த਎͸ Ϩεϙϯε

Slide 26

Slide 26 text

26 https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

Slide 27

Slide 27 text

ストリームの加⼯ 27 ストリーム上のデータに対して filter したり map したり merge したり zip し たり reduce したりできる オペレータと呼ばれる combineLatest や buffer など、時間 概念があるからこそのオペレータもある

Slide 28

Slide 28 text

filter 28 http://rxmarbles.com/#filter

Slide 29

Slide 29 text

map 29 http://rxmarbles.com/#map

Slide 30

Slide 30 text

merge 30 http://rxmarbles.com/#merge

Slide 31

Slide 31 text

zip 31 http://rxmarbles.com/#zip

Slide 32

Slide 32 text

reduce 32 http://rxmarbles.com/#reduce

Slide 33

Slide 33 text

combineLatest 33 http://rxmarbles.com/#combineLatest

Slide 34

Slide 34 text

buffer 34 http://reactivex.io/documentation/operators/ buffer.html

Slide 35

Slide 35 text

オペレータを組み合わせた例:ダブルタップ 35 https://gist.github.com/staltz/868e7e9bc2a7b8c1f754

Slide 36

Slide 36 text

ストリームを使ってできること 36 リスト処理 ⾮同期イベント処理 データバインディング Promise MVVM, etc.

Slide 37

Slide 37 text

例:テキストフィールドの変更をラベルに⾃動反映 37 textField.rx_text .map { "ʮ\($0)ʯ" } .bindTo(label.rx_text) .addDisposableTo(disposeBag)

Slide 38

Slide 38 text

例:条件を満たすまでボタンを押せないようにする 38 let textValidation = textField.rx_text .map { !$0.isEmpty } Observable.combineLatest( textValidation, loading.asObservable()) { text, loading in return text && !loading } .bindTo(submitButton.rx_enabled) .addDisposableTo(disposeBag)

Slide 39

Slide 39 text

例:インクリメンタルサーチ 39 textField.rx_text .debounce(0.5, scheduler: MainScheduler.instance) .distinctUntilChanged() .map { query -> Observable<[Item]> in if query.isEmpty { return Observable.just([]) } let request = GetItemsRequest(query: query) return API.responseFrom(request) } .switchLatest() .subscribeNext { [weak self] items in print("next: \(items.count)") self?.items = items self?.tableView.reloadData() } .addDisposableTo(disposeBag)

Slide 40

Slide 40 text

アッテの実例:画像アップロード後の投稿 40 画像のアップロードと投稿は別API 画像アップロードAPIで画像をアップロー ドするとメディアIDが発⾏される 投稿APIにはメディアIDの配列を渡す

Slide 41

Slide 41 text

すべての画像をアップロード後の新規投稿 41 combineLatest() ը૾̍ ը૾̎ ը૾̏ ը૾̐

Slide 42

Slide 42 text

⼀部の画像を再アップロード後の編集投稿 42 combineLatest() ը૾̍ ը૾̎ ը૾̏ ը૾̐

Slide 43

Slide 43 text

アッテの実例:新規投稿・編集投稿のコード 43 class Photo { var image: UIImage var mediaId: String? } var request = createUpdateRequest() photos .map { photo -> Observable in if let mediaId = photo.mediaId { return Observable.just(mediaId) } return ImageUploader.uploadImage(photo.image) } .combineLatest { $0 } .map { mediaIds -> Observable in request.mediaIds = mediaIds return APIClient.sharedClient.responseFrom(request) } .switchLatest() .subscribe( // ౤ߘAPIͷ݁ՌΛॲཧ ) .addDisposableTo(disposeBag)

Slide 44

Slide 44 text

Swiftにおける リアクティブプログラ ミング

Slide 45

Slide 45 text

Swiftにおけるリアクティブプログラミング 45 2015年10⽉時点での選択肢 • ReactiveCocoa • RxSwift • ReactKit

Slide 46

Slide 46 text

検討中の発表 46 https://speakerdeck.com/bricklife/swift-2-dot-0derxswift- reactkit-reactivecocoawoshi-tutemita

Slide 47

Slide 47 text

なぜRxSwiftか

Slide 48

Slide 48 text

RxSwiftのメリット その1 48 RxSwiftとはMicrosoftが2011年にリリース したReactive ExtensionsのSwift版 どの⾔語でもほぼ同じ仕様なので、約5年分 の資産がある RxSwiftは正式にReactiveXへ取り込まれた 開発やコミュニティが活発

Slide 49

Slide 49 text

RxSwiftのメリット その2 49 他⾔語でRxをしていた⼈は取り組みやすい 今後他⾔語でRxをやるときに経験が活かせ る AndroidではRxJavaがデファクトスタンダー ドなので設計が共有できる?

Slide 50

Slide 50 text

ReactiveCocoaとReactKitの評価 50 ReactiveCocoaは2015年の時点ではまだα 版で、Readme.mdに書かれているサンプ ルすらコンパイルできない状況… ReactKitは機能的に不⾜を感じた

Slide 51

Slide 51 text

vs ReactiveCocoa現⾏版 51 いまはReactiveCocoaもかなり成熟 特徴 • Cold ObservableとHot Observableを明確にクラスで分 けている(SignalとSignalProducer) • エラーに型がある • コードがきれいらしい(伝聞) どこかでちゃんと使ってみたい

Slide 52

Slide 52 text

RxSwiftのデメリット

Slide 53

Slide 53 text

RxSwiftのデメリット 53 RxSwift固有のデメリットはいまのところ あまり感じない 強いて⾔えばReactiveCocoaの特徴の反対 • Cold ObservableとHot Observableを混合 • エラーに型がない

Slide 54

Slide 54 text

リアクティブプログラミングのデメリット 54 学習コストが⾼い 設計に⼤きく影響(特にMVVM) ライブラリが巨⼤ もし開発が⽌まったらどうする? 頼りきっているとプログラミング能⼒が衰える?

Slide 55

Slide 55 text

チームへの浸透

Slide 56

Slide 56 text

有益な資料 56 【翻訳】あなたが求めていたリアクティブプ ログラミング⼊⾨ http://ninjinkun.hatenablog.com/entry/introrxja RxMarbles http://rxmarbles.com 公式ドキュメント(以下は有志の⽇本語版) https://github.com/tid-kijyun/RxSwift/wiki

Slide 57

Slide 57 text

チームへの浸透 57 前述のドキュメント 既存コード 実装パターンの共有 いい実装にはRPで をつける とにかくRxに触れる機会を増やす

Slide 58

Slide 58 text

とにかくRxに触れる機会を増やす 58 社内Slackに#tech-rxというRx全般の話をす るチャンネルを設置して、気軽に情報共有や 相談をできるようにしている Reactive Swift Meetupの企画 RxSwift勉強会への参加 ズンドコキヨシ with RxSwift

Slide 59

Slide 59 text

⼀緒に川遊びしま しょう!