なぜReactive Extensionsを導入するのか?

小飼です。LINEのプログラミング言語マスコットスタンプを濫用しています。

以前このブログでも触れましたが、現在弊社ではRxJSを本格的に活用してクライアントサイドアプリケーションを作成しています。

RxJSのクライアントサイドにおける有用性は、UIイベントの世界でコードを構築する側としては比較的すんなりと理解しやすいですが、
サーバーサイドやマネジメントレイヤーのメンバーなど、チーム内の別のポジションのメンバーには必ずしも理解しやすいとは限りません。

そこで、クライアントサイド以外のチームメンバー(もしかしたらビジネスレイヤーである顧客にも)にも、導入のメリットが把握できるように、RxJSの元となっているReactive Extensionsについて簡単にまとめました。
本稿ではReactive Extensionsの導入指南書である、Introduction to Rxを参考に、なぜReactive Extensionsなのか?いつRxを使うべきなのか?みたいなところを考えてみたいと思います。

このサイト及び同名の書籍は.NET開発者向けの内容ですが、Reactive Extensionsの基礎となる概念・型を解説していて、言語を問わずに理解の助けになると思うので、一読することをオススメします。
ちなみに私はAmazonで購入したのですが、後からこのサイトでフリー版がDLできることを知りました。
別にいいんですが。1ドルしないし。円高だし。

Reactive Extensionsとは?

端的に言えば、Reactive Programmingを実現するためのデザインと、その実装ライブラリを指すようです。
元々はMicroSoftが研究・開発した.NET用のライブラリでしたが、非常に有用な概念であったため、言語をまたいで移植されています。

RxJSはその一実装で、他にもRxJava、RxSwiftなど、いくつもの言語に移植されています。(RxJSはどちらかと言うと後発)
Reactive Extensionsの各言語実装リスト

それではそのReactive Programmingとは何でしょうか?

Qiitaに掲載されているリアクティブプログラミングの詳解記事にあった定義が簡潔でわかりやすいのでご紹介しますと、

「メッセージの送受信を隠蔽し値同士の関係(data-flow)を宣言的(関数型的)に記述するプログラミングパラダイム」です。

私は、値Aに即応する値Bを宣言するための考え方、といった捉え方をしています。
よくExcelのセル(あるセルAの値に即応するセルBを宣言できる)が、同じような概念の例として挙げられます。

なぜReactive Programmingなのか?

それではどんなメリットがあって、Reactive Extensionsを導入するのでしょうか?
(JavaScript界隈に限った話のような気がしますが)一般に学習コストが高いと言われるReactive Extensionsを導入することには、コストを償却し得るメリットがあるのでしょうか?

端的に言えば、生産性の大幅な向上が望めるからです。
何が生産性を上げるのか、大まかにまとめてみるとこんな区分ができると思っています。

  • Declarative(宣言的に書ける)
  • Transformative(変換できる)
  • Composable(組み合わせられる)

(加えてRxJS以外の実装では、スレッドハンドリングの容易性ということもあるようですが、ここでは置いておきます)

以下で各区分について、もう少し詳しく書いてみます。

Declarative(宣言的に書ける)

Reactive Extensionsを導入することで、同期データ・非同期イベントの別なく機能を宣言的に書くことができます。
これによって、非同期イベントであっても

  • パラメータAに何か施したら、パラメータBを変更するような命令的コードを、
  • パラメータBはパラメータAに応じて変換されるような宣言的コードとして

書くことができ、よりメンテナンスしやすい(=開発速度を落とさない)コードを構築することができるようになります。

Transformative(変換できる)

Reactive Extensionsの中心的な型の一つであるIObservable<T>型は、オペレータという仕組みによって、内包する型をIObservable<T> => IObservable<R>のように変換できます。
これによって、例えば何らかの検索機能を実装していると想定して、ユーザーがクリック入力したradioボタンの項目(IObservable<number>かも知れない)から検索条件(IObservable<{ [kye: string]: number}>)のような、抽象度の高いデータ型を労力少なく導き出すことができます。

Composable(組み合わせられる)

IObservable<T>型同士を組み合わせることで、更に抽象度の高い独自イベントを宣言できます。
前項の例を引き継いでサイト内検索機能を例に取ると、ユーザーが100ms毎にキー入力した文字列ユーザーがクリック入力したradioボタンの項目を組み合わせた、ユーザーの検索したい条件という独自イベントを簡単・簡潔に表現できます。

まとめると、同期データ・非同期イベントの別なく組み合わせることで抽象度の高い独自イベントを簡単・簡潔に宣言することで、生産性の大幅な向上が見込める、というところでしょうか。
(ここでいう簡単というのは、誰にでもできるという意味ではなく、ReactiveExtensionsを理解した上でコードを書く労力が少ない、という意味合いです)

いつReactive Extensionsを使うべきなのか?

では、実際にReactive Extensionsを活用すべきケースというのはどういう時なのでしょうか?
クライアントサイド領域に関係して向いているケースを挙げてみると…

UIイベント(ユーザーのクリック、キー入力、タップ、スワイプなど)

UIイベントを起点にしてユーザーの意図を実現することは、クライアントサイドで実装される主要な機能領域であると思います。
非同期イベントから抽象化された独自イベントを導き出すことは、Reactive Extensionsの主要な目的の一つですので、クライアントサイド実装は最も相性の良い領域と言えると思います。

I/Oイベント(ファイル読み書きや標準入出力)

タスクランナーのような、小さなCLIを作る時に、I/Oイベントを起点に抽象度の高いイベントを作り上げることができます。
有用ではあるものの、こちらはあまり頻出するケースでは無いかも知れません。


特にUIイベントは、クライアントサイド開発の中心領域であり、かつReactive Extensionsを活用することで最も恩恵を受けうる領域です。
RxJSの流行以前に、RxJavaやReactiveCocoaなどのReactive Extensions実装が流行しているのも、これが最も相性の良い組み合わせの一つだからだと考えています。

まとめ

以上、なるべくコードを使わずに概念だけでReactive Extensions導入のメリットを説明してみました。
参考になればうれしいです。

このエントリーをはてなブックマークに追加