リアクティブプログラミング(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.net | RxJS、Rx.NETなどのGithubページ |
ReactiveX | RxSwift、RxJavaなどのGithubページ |
UniRx | UniRxの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を実装するためのライブラリ集
ライブラリ | 解説 |
---|---|
Reactive | Franに似た古典的FRPライブラリ |
Yampa | Signal Functionを用いるArrowised FRP。Yale Haskell Groupが開発 |
Grapefruit | オブザーバーパターンがPush式のFRP |
関連記事
- 2024/01/25 TypeScriptで名前付き引数っぽい実装をする TypeScriptでPythonのように関数呼び出し時に引数名を使って「名前=値」の形式で引数を指定するOptions Objectパターンという技を紹介します。
- 2023/10/17 コードの品質を測定する方法 コードの品質を測定する方法が紹介されていました。計測の自動化に向けて、少しまとめてみました。
- 2023/01/26 デメテルの法則 「直接の友達とだけ話すこと」というプログラミングのお約束です
- 2020/06/15 PySparkの分散される処理単位であるクロージャと共有変数の仕組み Spark では、処理が分散されて、複数のノードやスレッドで実行されますが、分散される処理の塊を、どう配信しているのか?加えて、複数のタスク間でのデータの共有とか、集約するための仕組みがどうなっているのか?少しだけ説明します。
- 2019/09/24 「オブジェクト指向エクササイズ」でクセの強いコードを矯正しよう よくできたコードは、パッと見で、”なんか違う”と感じさせるところがあり、あぁ、このコードを書いた人はデキるって思わせるものですが、そんなコードを書くためには、どうしたらよいんでしょうか?そのヒントが「オブジェクト指向エクササイズ」にあります。