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ライフを!