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

Rx入門

52604f94a6d2172df2cad5ab45189940?s=47 ponday
November 21, 2017

 Rx入門

Rx勉強会@福岡 #0 発表資料

学習コストは高いけど使いこなせると強力だよっていうことを言いたかった。

52604f94a6d2172df2cad5ab45189940?s=128

ponday

November 21, 2017
Tweet

More Decks by ponday

Other Decks in Technology

Transcript

  1. Rx入門 Rx勉強会@福岡 #0 / Nov 21, 2017 ponday (@ponday_dev)

  2. 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
  3. ご注意

  4. ご注意 - サンプルコードはRxJS 5.5で記載しています - 他言語利用者の方、すみません。 - 他言語のライブラリとの互換性の観点から、Lettable Operatorsは使用してい ません。

    - 予約語などの兼ね合いから、他の言語と関数名が一致していない場合があり ます。 - 極力コードは解説しますが、漏れや分かりにくい点があれば 遠慮なく聞いてください
  5. Rxとは?

  6. Rxとは - ReactiveX / Reactive Extensionsのこと - 関数型リアクティブプログラミング向けのライブラリ - FRP

    / Functional Reactive Programmingとも - 厳密にはFRPではない、という批判も一部業界からあるようなので非同期処理 向けのライブラリ、と思っておけば良い - MicrosoftがC#向けに開発した『Rx.NET』が元 - NetflixがJavaへの移植版である『RxJava』をリリースしたことによ り注目度が高まる - アプリ、WebのUI部分での利用が多い (RxJS, RxSwift, RxJava...)
  7. 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)
  8. Observerパターン - GoFで提唱されたデザインパターンの一つ - Pub/Subパターンとも - Rxの根底にある考え方 - 以下のような場合に有効 -

    イベントドリブンなプログラム - 状態の変化に応じて処理が発生するプログラム - アプリのUI部分やWebでは上記のような処理が頻出 → Rxが有効に活用できる
  9. サンプル - 数値の入力欄2つ - 計算ボタンをクリックして2値の加減乗除の計算をする - ↓こんなの

  10. よくあるイベント処理の場合

  11. 書ける(当然)

  12. 何が問題? ※ バリデーションとかは別として

  13. ここ

  14. ここ

  15. 問題点 - 計算ボタンのクリックイベントで加減乗除を計算して、各要素 のテキストに反映している - ボタン自身がクリックされることによって変更される要素を知っていなければな らない - さらに、各要素に入力される値の規則も知っていなければならない -

    要するに、結合が密 - 余りの計算を追加したくなったら、イベントハンドラが膨らむ - 追加/変更に弱い
  16. Observerパターンを適用してみる

  17. こんなオブジェクトを定義

  18. イベント処理を置き換え

  19. イベント処理を置き換え

  20. イベントハンドラ部分の比較

  21. イベントハンドラ部分の比較 - イベントハンドラ内に各要素の値更新のロジックが無くなった - data.suscribeで処理を外部から登録すれば良いので、別のファイルやオブジェ クトに分割も可能 - 余りの計算が追加されてもイベントハンドラに変更は発生しない - イベントを発生させるオブジェクトは自身の影響範囲を知らな

    くて良い
  22. RxJSで書くとこう

  23. 用語など

  24. ストリーム - データの流れのこと - よくストリームが「川」、データが「桃」に例えられる - 個人的にはこの例えイマイチ... - 自動車の生産ラインとかに例えるほうが具体的 -

    配列などから生成される他、イベントを一つのデータとみなし てイベントの発生を待ち受けるストリームなどもある
  25. ※ 公式サイトなどでよく見る図

  26. オペレータ - Rxが提供しているメソッド群 - 自動車の生産ラインに例えるなら、次のようなもの - 自動車の塗装 (データの加工) - 品質検査

    (データの選別) - ドアの取付 (ストリームの合成)
  27. 大きく分けると2種類

  28. ① データソースの定義

  29. そのストリームに流れるデータは何から発生するか? (固定値、配列、時間経過、イベント...)

  30. ※ 公式サイトなどでよく見る図

  31. ② データの操作

  32. データを受け取ったら何をするか? (加工、選別、合成、分岐...)

  33. ※ 公式サイトなどでよく見る図

  34. subscribe - ストリームの処理のうち、最後の「加工結果の受け取り」にあ たるメソッド - 原則として、subscribeすることでストリーム内にデータが流れ 始める - next /

    error / completeの3種類の処理が定義できる - next データが流れて来るたびに実行 - error ストリーム内でエラーが発生したときに実行 ストリームが終了する - complete ストリーム内を全てのデータが流れきったときに実行 ストリームが終了する
  35. unsubscribe / dispose - ストリームには「勝手に終了するもの」と「勝手に終了しないも の(半永久的に続くもの)」がある。 - 配列から値を取り出して順にデータとして流す   → 配列のデータを全て流したら終わり

    - 2秒経ったらデータを流す   → 2秒後にデータを流したら終わり - 1秒ごとにデータを流す   → 常に次の1秒は存在するので半永久的に続く - イベントが発生したらデータを流す   → イベントはいつまでも発生し得る = 半永久的に続く - subscribeで開始したデータの受け取りを明示的に終了させる ために使う。
  36. 処理の流れ データの 発生 加工、抽出 分岐、合成 データの 受け取り ストリームの 破棄 ※

    繰り返し
  37. Rxの特徴

  38. メソッドチェーンによる簡潔な記述 - オペレータ一つが一つの処理になる → どこでなにをしているのか明確 - 複数の非同期処理でもネストの深さが一定に保てる ※ 1~100の合計を計算 ※

    30秒毎に自動的にニュースを取得しにいく
  39. 豊富なオペレータ - 目的に応じた非常に多くのオペレータを提供 - RxJS 5系で90個ほど - 他言語では100を超えるものも多い - 実際によく使うのはせいぜい20~30個程度

    - 他のオペレータで代用が効くものもあるので、全て覚える必要ななし - 制御構文に当たるものはRxが提供 開発者は流れてきたデータに対する処理に集中すればOK - 既存のプログラムとの互換性のためのユーティリティも提供し ている(JSで言えばPromiseとの相互変換など)
  40. 全てが非同期 - データの受け取りは必ず非同期的に行われる - ハマりポイントの一つ - subscribeして以降はデータが流れてくるたびに勝手に処理してくれる - 1つのストリームの中は同期的に処理が進む (map

    -> filterと書いておけばがfilter -> mapの順で実行されることはない) - 複数の非同期処理を制御するためのオペレータもある - mergeMap 複数の非同期処理を並列実行 - concatMap 複数の非同期処理を直列実行 - switchMap 後勝ち。既存の処理をキャンセル - exhaustMap 先勝ち。新しい処理を実行させない。
  41. 適用可能範囲の広さ - 元々FRPを実現するために作られたライブラリ - FRPは汎用的なプログラミングパラダイム - メソッドチェーンの外にifやforを書かないプログラミングも十分 可能 - おすすめはしません

    - 得意分野はリスト処理と非同期処理 - リスト処理だけなら最近は大抵の言語に実装されてるので... - 非同期処理の制御はかなり強力
  42. Rxのデメリット

  43. 学習コストの高さ - そもそもプログラミングのパラダイムが異なるので当然といえ ば当然 - 一つの新しい言語を学んでいるようなもの - オペレータも少なくとも20~30は覚える必要がある - 処理に応じてRxを使うべきか言語構文を使うべきかの判断が

    必要になる - Rx特有のハマりポイントも多い ※ 拡張性が低い、という批判もあるが個人的にはNo   そういう場合、大抵は複数のデータを1本で管理しようとしている   1つのストリーム = 1つのデータ/操作を守っていれば拡張は容易
  44. Rxの採用について

  45. 大前提として

  46. Rx ≠ 銀の弾丸

  47. Rx ≠ 銀の弾丸 - プログラミングパラダイム毎に得手不得手がある - どこにでも適用すれば便利になる、ということはない - 適用することが有効なところで使ってこそ活きる →

    他のライブラリでも同じ - Rxでやれば簡単に書けるところはある - 逆に、Rxを使うと複雑になるところも当然ある - 「Rx使ってみたけどイマイチメリットが...?」 - 使い所間違っていませんか? - 適切に使い分けができるよう、自身の判断基準を養うところも 学習コスト
  48. Rxを使ったほうが良い場合

  49. 言語のリスト処理が貧弱な場合 - 昔のAndroid Javaのパターン - ストリーム ≒ 配列はイメージしやすく適用が容易 - map,

    filter, reduceなどが必要な場合に - 当然非同期的に結果を受け取ることになるので良し悪し - 言語組み込みのmap, filter, reduceは動的的なので間隔は若干異なる
  50. 非同期処理が必要な場合 - イベント処理 - UI上のユーザアクションはよくある非同期処理の例 - debounce, throttleはもちろん、多重クリックの制御や検知にも - API呼び出し

    - こちらも代表的な非同期処理 - 特に複数のAPI呼び出しが絡む場合は非常に便利 - イベント処理同様、多重実行の制御が簡単 - 「このAPIのレスポンスを使って次のAPIを呼び出す」といった待ち受けも簡単 - 状態管理 - 動的に変更され得る状態は「状態が変更される」という非同期的なイベントを 持っている - Observerパターンが得意とするところ
  51. Rxを使わないほうが良い場合

  52. 非同期処理がない、少ない - 非同期処理がないのに非同期処理を組み込む意味は...? - リスト処理が貧弱な場合は別 - 非同期処理がシンプルかつ少なく、言語標準の非同期処理が 簡単な言語なら採用しないという判断もあり - JavaScript

    (Promise) - Go (goroutine)
  53. Rx採用のすゝめ

  54. Rxを採用するなら - 全てをRxで書こうとしない - 手続き型で簡単に書けるところをRxで置き換えても旨味がない - Rxで書いてみて、「これは手続きで書くほうが楽」と感じる処理は素直にそれ に従ったほうが良い - 慣れてくるとどちらが楽か何となくつかめる

    - まずは小さく適用する - 慣れてないうちに書いたコードは実装にムリが出がち - 切り出せる部分に順次適用して行くのが吉 - できれば複数人で - これは個人的に一人で書いてて思ったこと - 同じことをするのに何パターンもの書き方がある - 「こんな書き方もできる」という引き出しが多いほうが良い - ペアプログラミングがかなり有効そうな気がする
  55. まとめ

  56. まとめ - Rxは非同期処理が得意なライブラリ - 複数の非同期処理が絡む場合に威力を発揮 - プログラミングパラダイムが異なるので学習コストはちょっと高 め - Rx

    ≠ 銀の弾丸 - 元言語と得手、不得手を比較して選定を
  57. 良いRxライフを!