Rx入門
by
ponday
Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
Rx入門 Rx勉強会@福岡 #0 / Nov 21, 2017 ponday (@ponday_dev)
Slide 2
Slide 2 text
Profile Honda, Yusuke (@ponday_dev) Community - chibi-developer - ng-fukuoka Like - JavaScript / TypeScript / Kotlin - RxJS / Angular / Vue.js Other skills - C# / Java / Python - Spring Boot SIer / System Engineer
Slide 3
Slide 3 text
ご注意
Slide 4
Slide 4 text
ご注意 - サンプルコードはRxJS 5.5で記載しています - 他言語利用者の方、すみません。 - 他言語のライブラリとの互換性の観点から、Lettable Operatorsは使用してい ません。 - 予約語などの兼ね合いから、他の言語と関数名が一致していない場合があり ます。 - 極力コードは解説しますが、漏れや分かりにくい点があれば 遠慮なく聞いてください
Slide 5
Slide 5 text
Rxとは?
Slide 6
Slide 6 text
Rxとは - ReactiveX / Reactive Extensionsのこと - 関数型リアクティブプログラミング向けのライブラリ - FRP / Functional Reactive Programmingとも - 厳密にはFRPではない、という批判も一部業界からあるようなので非同期処理 向けのライブラリ、と思っておけば良い - MicrosoftがC#向けに開発した『Rx.NET』が元 - NetflixがJavaへの移植版である『RxJava』をリリースしたことによ り注目度が高まる - アプリ、WebのUI部分での利用が多い (RxJS, RxSwift, RxJava...)
Slide 7
Slide 7 text
Rxファミリー - Rx.NET (C#) - RxJava (Java) - RxSwift (Swift) - RxJS (JavaScript) - RxKotlin (Kotlin) - UniRx (Unity C#) - RxScala (Scala) - RxClojure (Clojure) - RxCpp (C++) - Rx.rb (Ruby) - RxPY (Python) - RxGo (Go) - RxGroovy (Groovy) - RxJRuby (JRuby) - RxPHP (PHP) - reactive (Elixir) - RxDart (Dart)
Slide 8
Slide 8 text
Observerパターン - GoFで提唱されたデザインパターンの一つ - Pub/Subパターンとも - Rxの根底にある考え方 - 以下のような場合に有効 - イベントドリブンなプログラム - 状態の変化に応じて処理が発生するプログラム - アプリのUI部分やWebでは上記のような処理が頻出 → Rxが有効に活用できる
Slide 9
Slide 9 text
サンプル - 数値の入力欄2つ - 計算ボタンをクリックして2値の加減乗除の計算をする - ↓こんなの
Slide 10
Slide 10 text
よくあるイベント処理の場合
Slide 11
Slide 11 text
書ける(当然)
Slide 12
Slide 12 text
何が問題? ※ バリデーションとかは別として
Slide 13
Slide 13 text
ここ
Slide 14
Slide 14 text
ここ
Slide 15
Slide 15 text
問題点 - 計算ボタンのクリックイベントで加減乗除を計算して、各要素 のテキストに反映している - ボタン自身がクリックされることによって変更される要素を知っていなければな らない - さらに、各要素に入力される値の規則も知っていなければならない - 要するに、結合が密 - 余りの計算を追加したくなったら、イベントハンドラが膨らむ - 追加/変更に弱い
Slide 16
Slide 16 text
Observerパターンを適用してみる
Slide 17
Slide 17 text
こんなオブジェクトを定義
Slide 18
Slide 18 text
イベント処理を置き換え
Slide 19
Slide 19 text
イベント処理を置き換え
Slide 20
Slide 20 text
イベントハンドラ部分の比較
Slide 21
Slide 21 text
イベントハンドラ部分の比較 - イベントハンドラ内に各要素の値更新のロジックが無くなった - data.suscribeで処理を外部から登録すれば良いので、別のファイルやオブジェ クトに分割も可能 - 余りの計算が追加されてもイベントハンドラに変更は発生しない - イベントを発生させるオブジェクトは自身の影響範囲を知らな くて良い
Slide 22
Slide 22 text
RxJSで書くとこう
Slide 23
Slide 23 text
用語など
Slide 24
Slide 24 text
ストリーム - データの流れのこと - よくストリームが「川」、データが「桃」に例えられる - 個人的にはこの例えイマイチ... - 自動車の生産ラインとかに例えるほうが具体的 - 配列などから生成される他、イベントを一つのデータとみなし てイベントの発生を待ち受けるストリームなどもある
Slide 25
Slide 25 text
※ 公式サイトなどでよく見る図
Slide 26
Slide 26 text
オペレータ - Rxが提供しているメソッド群 - 自動車の生産ラインに例えるなら、次のようなもの - 自動車の塗装 (データの加工) - 品質検査 (データの選別) - ドアの取付 (ストリームの合成)
Slide 27
Slide 27 text
大きく分けると2種類
Slide 28
Slide 28 text
① データソースの定義
Slide 29
Slide 29 text
そのストリームに流れるデータは何から発生するか? (固定値、配列、時間経過、イベント...)
Slide 30
Slide 30 text
※ 公式サイトなどでよく見る図
Slide 31
Slide 31 text
② データの操作
Slide 32
Slide 32 text
データを受け取ったら何をするか? (加工、選別、合成、分岐...)
Slide 33
Slide 33 text
※ 公式サイトなどでよく見る図
Slide 34
Slide 34 text
subscribe - ストリームの処理のうち、最後の「加工結果の受け取り」にあ たるメソッド - 原則として、subscribeすることでストリーム内にデータが流れ 始める - next / error / completeの3種類の処理が定義できる - next データが流れて来るたびに実行 - error ストリーム内でエラーが発生したときに実行 ストリームが終了する - complete ストリーム内を全てのデータが流れきったときに実行 ストリームが終了する
Slide 35
Slide 35 text
unsubscribe / dispose - ストリームには「勝手に終了するもの」と「勝手に終了しないも の(半永久的に続くもの)」がある。 - 配列から値を取り出して順にデータとして流す → 配列のデータを全て流したら終わり - 2秒経ったらデータを流す → 2秒後にデータを流したら終わり - 1秒ごとにデータを流す → 常に次の1秒は存在するので半永久的に続く - イベントが発生したらデータを流す → イベントはいつまでも発生し得る = 半永久的に続く - subscribeで開始したデータの受け取りを明示的に終了させる ために使う。
Slide 36
Slide 36 text
処理の流れ データの 発生 加工、抽出 分岐、合成 データの 受け取り ストリームの 破棄 ※ 繰り返し
Slide 37
Slide 37 text
Rxの特徴
Slide 38
Slide 38 text
メソッドチェーンによる簡潔な記述 - オペレータ一つが一つの処理になる → どこでなにをしているのか明確 - 複数の非同期処理でもネストの深さが一定に保てる ※ 1~100の合計を計算 ※ 30秒毎に自動的にニュースを取得しにいく
Slide 39
Slide 39 text
豊富なオペレータ - 目的に応じた非常に多くのオペレータを提供 - RxJS 5系で90個ほど - 他言語では100を超えるものも多い - 実際によく使うのはせいぜい20~30個程度 - 他のオペレータで代用が効くものもあるので、全て覚える必要ななし - 制御構文に当たるものはRxが提供 開発者は流れてきたデータに対する処理に集中すればOK - 既存のプログラムとの互換性のためのユーティリティも提供し ている(JSで言えばPromiseとの相互変換など)
Slide 40
Slide 40 text
全てが非同期 - データの受け取りは必ず非同期的に行われる - ハマりポイントの一つ - subscribeして以降はデータが流れてくるたびに勝手に処理してくれる - 1つのストリームの中は同期的に処理が進む (map -> filterと書いておけばがfilter -> mapの順で実行されることはない) - 複数の非同期処理を制御するためのオペレータもある - mergeMap 複数の非同期処理を並列実行 - concatMap 複数の非同期処理を直列実行 - switchMap 後勝ち。既存の処理をキャンセル - exhaustMap 先勝ち。新しい処理を実行させない。
Slide 41
Slide 41 text
適用可能範囲の広さ - 元々FRPを実現するために作られたライブラリ - FRPは汎用的なプログラミングパラダイム - メソッドチェーンの外にifやforを書かないプログラミングも十分 可能 - おすすめはしません - 得意分野はリスト処理と非同期処理 - リスト処理だけなら最近は大抵の言語に実装されてるので... - 非同期処理の制御はかなり強力
Slide 42
Slide 42 text
Rxのデメリット
Slide 43
Slide 43 text
学習コストの高さ - そもそもプログラミングのパラダイムが異なるので当然といえ ば当然 - 一つの新しい言語を学んでいるようなもの - オペレータも少なくとも20~30は覚える必要がある - 処理に応じてRxを使うべきか言語構文を使うべきかの判断が 必要になる - Rx特有のハマりポイントも多い ※ 拡張性が低い、という批判もあるが個人的にはNo そういう場合、大抵は複数のデータを1本で管理しようとしている 1つのストリーム = 1つのデータ/操作を守っていれば拡張は容易
Slide 44
Slide 44 text
Rxの採用について
Slide 45
Slide 45 text
大前提として
Slide 46
Slide 46 text
Rx ≠ 銀の弾丸
Slide 47
Slide 47 text
Rx ≠ 銀の弾丸 - プログラミングパラダイム毎に得手不得手がある - どこにでも適用すれば便利になる、ということはない - 適用することが有効なところで使ってこそ活きる → 他のライブラリでも同じ - Rxでやれば簡単に書けるところはある - 逆に、Rxを使うと複雑になるところも当然ある - 「Rx使ってみたけどイマイチメリットが...?」 - 使い所間違っていませんか? - 適切に使い分けができるよう、自身の判断基準を養うところも 学習コスト
Slide 48
Slide 48 text
Rxを使ったほうが良い場合
Slide 49
Slide 49 text
言語のリスト処理が貧弱な場合 - 昔のAndroid Javaのパターン - ストリーム ≒ 配列はイメージしやすく適用が容易 - map, filter, reduceなどが必要な場合に - 当然非同期的に結果を受け取ることになるので良し悪し - 言語組み込みのmap, filter, reduceは動的的なので間隔は若干異なる
Slide 50
Slide 50 text
非同期処理が必要な場合 - イベント処理 - UI上のユーザアクションはよくある非同期処理の例 - debounce, throttleはもちろん、多重クリックの制御や検知にも - API呼び出し - こちらも代表的な非同期処理 - 特に複数のAPI呼び出しが絡む場合は非常に便利 - イベント処理同様、多重実行の制御が簡単 - 「このAPIのレスポンスを使って次のAPIを呼び出す」といった待ち受けも簡単 - 状態管理 - 動的に変更され得る状態は「状態が変更される」という非同期的なイベントを 持っている - Observerパターンが得意とするところ
Slide 51
Slide 51 text
Rxを使わないほうが良い場合
Slide 52
Slide 52 text
非同期処理がない、少ない - 非同期処理がないのに非同期処理を組み込む意味は...? - リスト処理が貧弱な場合は別 - 非同期処理がシンプルかつ少なく、言語標準の非同期処理が 簡単な言語なら採用しないという判断もあり - JavaScript (Promise) - Go (goroutine)
Slide 53
Slide 53 text
Rx採用のすゝめ
Slide 54
Slide 54 text
Rxを採用するなら - 全てをRxで書こうとしない - 手続き型で簡単に書けるところをRxで置き換えても旨味がない - Rxで書いてみて、「これは手続きで書くほうが楽」と感じる処理は素直にそれ に従ったほうが良い - 慣れてくるとどちらが楽か何となくつかめる - まずは小さく適用する - 慣れてないうちに書いたコードは実装にムリが出がち - 切り出せる部分に順次適用して行くのが吉 - できれば複数人で - これは個人的に一人で書いてて思ったこと - 同じことをするのに何パターンもの書き方がある - 「こんな書き方もできる」という引き出しが多いほうが良い - ペアプログラミングがかなり有効そうな気がする
Slide 55
Slide 55 text
まとめ
Slide 56
Slide 56 text
まとめ - Rxは非同期処理が得意なライブラリ - 複数の非同期処理が絡む場合に威力を発揮 - プログラミングパラダイムが異なるので学習コストはちょっと高 め - Rx ≠ 銀の弾丸 - 元言語と得手、不得手を比較して選定を
Slide 57
Slide 57 text
良いRxライフを!