リアクティブプログラミングの概観と、各言語での実装について

リアクティブプログラミング(reactive programming)とは?

最近、リアクティブプログラミングという言葉を目にすることが多くなりました。
リアクティブプログラミングは、CPUのマルチコア化やクラウドの活用が進む中で、 非同期通信に基づいたアプリケーションの設計に適しているため、 これからのソフトウェア開発における重要な技術として注目されています。

まず、以下の擬似コードを見てみましょう。

a = 1
b = 2 * a
a = 2
print b

プログラマに対して無前提にこのコードの出力結果を訊けば「2」と答えるかと思います。
しかし、リアクティブプログラミングの観点でみると「4」が出力されるべき、という答えになります。
というのは、リアクティブプログラミングの観点では、2行目の「b = 2 * a」というコードは 「bをaの2倍として定義する」という意味で解釈されるからです。

つまり、aとbの関係性を定義した後は、「aへの代入」というeventへのリアクションとして 「bの再計算」を常にバックグラウンドで行う、このようなパラダイムのことをリアクティブプログラミングと呼びます。

リアクティブプログラミングのメリット

これまでの命令型プログラミングでは、特に非同期の並行処理において様々な問題がありました。
例えば、

  • コードが複雑化する
  • 命令の実行順序を管理することができない
  • 幾重にもネストされたコールバック(いわゆるコールバック地獄)

などです。

リアクティブプログラミングを活用すると、シンプルなコードで上記を記述し、アプリケーションの動作を管理することが可能になります。

リアクティブプログラミングの技法的な特徴

behaviorとeventというパラダイム

リアクティブプログラミングでは、時間の関数として与えられる「behavior」と、 時間と値の組である「event」で処理を記述していきます。
behaviorは時間を通じて変化する値であり、eventはある時間においてbehaviorに働きかけるもの、と考えることができます。
例えばブランコの動きを制御するプログラムを書いた時、behaviorとして「ブランコの位置」「ブランコの速度」というものが考えられ、これらは相互に関係します。
またeventとして「ブランコを押す(実装の一例として、ブランコの速度に定数を足す)」というものを考える事ができます。
他にも様々なeventを定義する事で、ブランコの多様な動きを制御したり、複数のブランコを組み合わせたり、別の概念と関連させたリアクティブアプリケーションを作ることができます。

上記の例では、a、bという変数がそれぞれbehaviorに当たります。
「b = 2 * a」という式がbehaviorどうしの関係性を記述し、ある時刻に起きた「a = 2」というeventがaのみならずbも変化させるという実装を示唆しています。

GoFのオブザーバーパターン(Observer pattern)

後述する各種プログラミング言語のリアクティブプログラミングのための拡張である Rx ライブラリは、その根幹にオブザーバーパターンという考え方を持っています。

オブザーバーパターンは1995年にGoF(Gang of Four)によって提案された23のデザインパターンの一つであり、プログラムのインタフェースとしては古典的なものです。
Subject(監視対象)とObserver(観察者)からなるパラダイムで、利用シーンとしては、GUIの設計においてデータベースの変更を検知して表示を自動更新したい場合などが代表的です。
実装の概略は以下の通りです:

  • 監視対象のオブジェクトに観察者を登録する(このことから、観察者は購読者(subscriber)とも呼ばれる)
  • 監視対象のデータベースに変更があった際にメソッドが呼び出され、すべての観察者に変更が通知される
  • 監視対象、観察者はお互いの内部設計を知らなくてもよい

GUIの例においては、GUIクラスが「観測者」、データ処理クラスが「監視対象」ということになります。
オブザーバーパターンを用いることの利点は、観察者の実装に変更が加えられたとしても、監視対象の実装を変更しなくても良いという点です。
MVC(Model View Controller)モデルにおいてModelの設計がViewの設計に依存するというのはありがちなことです。
オブザーバーパターンでは通知のメソッドさえ共有されていれば良く、一方の変更によって他方を設計し直す必要がありません。
そのため、拡張可能性の高いアプリケーションが開発出来ることが知られています。
以下で説明するRxライブラリにおいて、オブザーバーパターンに準拠したクラスが実装されています。

Rx(Reactive Extensions)

Rx(Reactive Extensions)とは各言語においてリアクティブプログラミングを実現させる拡張機能を指します。
2009年からMicrosoft DevLabsにおいて進行していたプロジェクトであり、2011年に製品化され様々な分野で非同期処理が可能となりました。

C#・LINQ(Language Integrated Query)におけるRx

LINQはC# 3.0から追加された機能であり、元々はC#に対してSQLライクなクエリやRDB操作を可能にしたものでした。
そこに非同期処理やイベント処理を可能にする機能拡張が行われました。
LINQ to Objectsという従来の機能に対比させて、LINQにおけるRxをLINQ to Eventsと呼ぶこともあります。
Rxの記法はLINQの記法に似ていますので、前提知識としてLINQを知っていると習得に有利です。

各言語のRxライブラリ

2009年にマイクロソフトが提供開始したのRx.NETを皮切りに、RxJava、RxJS、RxSwiftなど様々な言語向けにRxライブラリが開発されてきました。
またマイクロソフト外のチームが開発したRxライブラリもあり、UnityのRxであるUniRxなどが挙げられます。

参考サイト説明
Reactive.netRxJS、Rx.NETなどのGithubページ
ReactiveXRxSwift、RxJavaなどのGithubページ
UniRxUniRxのGithubページ

FRP(Functional Reactive Programming)

リアクティブプログラミングの研究を早くから進めていたのがHaskellユーザーで、Conal Elliotによる1997年の論文が有名です。 (参考: http://conal.net/papers/icfp97/)。 Haskellのような関数型言語で実現されるリアクティブプログラミングをFRP(functional reactive programming, 関数型リアクティブプログラミング)と呼びます。 上記の論文に準拠する「Fran」というHaskellで記述されたシステムのチュートリアルは、リアクティブプログラミングの事始めとして多くのプログラマに親しまれています。(参考: http://conal.net/fran/tutorial.htm) このページでは複数の男の子の顔面がダンスをするという滑稽なアニメーションが公開されており、従来のプログラムに比べてFRPでは非常に簡潔に記述出来る事を述べています。

HaskellでFRPを実装するためのライブラリ集

ライブラリ解説
ReactiveFranに似た古典的FRPライブラリ
YampaSignal Functionを用いるArrowised FRP。Yale Haskell Groupが開発
GrapefruitオブザーバーパターンがPush式のFRP

関連記事

\(^▽^*) 私たちと一緒に働いてみませんか? (*^▽^)/

少しでも興味をお持ちいただけたら、お気軽に、お問い合わせください。

採用応募受付へ

(採用応募じゃなく、ただ、会ってみたいという方も、大歓迎です。)