SwiftでReactive Programming

# はじめに
ここ数年で注目を集めて続けているReactive Programmingですが、Swiftにもライブラリとして提供されていたり、実際にサービスにも多く導入されていることから、Reactiveのことからライブラリまで調べてみました。今回はじめてReactiveに入門したので何か指摘点等あれば気軽にコメント頂けると幸いです。

# 概念から学ぶ
まずは、Reactiveの概念中心の内容になります。


- <a href="#reactive_summary">Reactiveとは</a>
- <a href="#ra">Reactive Application</a>
- <a href="#rp">Reactive Programming</a>
- <a href="#frp">Functional Reactive Programming</a>
- <a href="#rx_swift">RxSwift</a>
- <a href="#rx">Reactive Extensions</a>
- <a href="#rx_cocoa">RxCocoa</a>

初めに<a href="#sample">サンプルコードから学ぶ</a>を軽く見た方がイメージが湧きやすいかもしれないです。

# <a name="reactive_summary">Reactiveとは

***Reactive***というキーワードは特にエンジニアなら聞いたことはあるかと思いますが、Reactiveという概念自体、***Reactive Application***と、***Reactive Programming***二つの意味を指すことが多いようです。

## <a name="ra">Reactive Application
まずReactiveの定義ですが、Jonas BonerとBruce Eckelによって発表された<a href="http://www.reactivemanifesto.org/" target="_blank">The Reactive Manifesto</a>にReactiveというアプリケーションはどのようなものか説明がされています。

> we want systems that are Responsive, Resilient, Elastic and Message Driven. We call these Reactive Systems.
(一部抜粋)

即応性、耐障害性、弾力性、メッセージ駆動を備えたシステムをReactive Systemsとして定義してます。障害が起きても落ちることがなく、高い即応性を保ち続けることでユーザが期待するインタラクティブなUX(ユーザー体験)を提供するシステムのことを指しているようですね。すなわち、ここで言われているReactiveとは***ユーザが期待する即応性を保ち続ける思想***のことを意味しているようです。近年、アプリケーションで高いUXが追求されきていることからも、今後Reactive Systemsの重要性は高まっていくと考えられます。

<p align="center"><img width="450" alt="スクリーンショット 2016-05-26 22.02.11.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/e3758484-bccb-ab69-7e72-dd65d6682f30.png"></p>

<dl>
 <dt>Message Driven(メッセージ駆動)</dt>
 <dd>イベントごとに非同期的に送受信を行うイベント駆動型であることで、次の3つの性質を生む</dd><br>
 <dt>1. Responsible(即応性)</dt>
 <dd>迅速かつ一貫した応答時間を提供する</dd><br>
 <dt>2. Resilient(耐障害性)</dt>
 <dd>障害に直面しても即応性を保ち続ける</dd><br>
 <dt>3. Elastic(即弾力性)</dt>
 <dd>ワークロード(負荷)が変動しても即応性を保ち続ける</dd><br>
</dl>

## <a name="rp">Reactive Programming

Reactive Applicationを実現するために用いられるReactive Programming(以降RP)ですが、Wikipediaでは次のように述べられています。

>In computing, reactive programming is a programming paradigm oriented around data flows and the propagation of change. This means that it should be possible to express static or dynamic data flows with ease in the programming languages used, and that the underlying execution model will automatically propagate changes through the data flow.
<a href="https://en.wikipedia.org/wiki/Reactive_programming" target="_blank">英語版Wikipedia / Reactive programming</a>

つまりRPとは、***時間と共に変化する(動的な)値とそれに対する関係性を記述してプログラミングを行うパラダイム***になります。RPを用いることで値の状態が変化した時に自動的に値が変更されることになります。

### オブジェクト思考における状態管理

オブジェクト指向型プログラミングでは、状態の依存関係がある場合(値が変更された時に、他の値やオブジェクトを更新しなくてはならないなど)、初期化やObserverパターンを用いた状態更新のロジック、必要であればキャッシュのロジックなどを記述する必要があります。Swiftでは、`NSNotificationCenter`を用いたObserverパターンがありますが、一つ一つのイベントに対して`removeObserver()`などでメモリを解放する必要がり、バグの温床にもなりかねないですね。
RPではこれらの状態更新やキャッシュが自動的に行われるため、***私たちは状態が変更された場合にどのように振る舞うか宣言的な式を記述するだけ***になるのです。

### RPとエクセルの表計算

RPの例えとしてよく使われるのがエクセルの表計算です。以下のシートの`A3`, `B3`にはそれぞれ`=A1+B1`, `=A1*B1`が入力してあります。

<p align="center">![excel.gif](https://qiita-image-store.s3.amazonaws.com/0/62451/311ef337-ca73-7b8a-060c-05d3c19d1d7d.gif)

`=A1+B1`, `=A1*B1`という関係式が記述されてるだけで、`A1`と`B1`の値を変更すると自動的に値が変更されているのがわかるかと思います。これこそまさにRPが実現できていると言えますね。

## <a name="frp">Functional Reactive Programming

RPを関数型プログラミング実装にさせたのがFunctional Reactive Programming(以降FRP)と言われるものです。

> FRP is programming with asynchronous data streams
<a href="http://ninjinkun.hatenablog.com/entry/introrxja" target="_blank">【翻訳】あなたが求めていたリアクティブプログラミング入門</a>

FRPはよく非同期データストリームを用いるプログラミングであると言われることからも、FRPを理解する上でデータストリームの概念をつかむことが重要とされています。ストリームは、変数、ユーザー入力、プロパティ、キャッシュ、データ構造など何に対してでも表現することができます。

さて、先ほどRPとは***時間と共に変化する(動的な)値とそれに対する関係性を記述してプログラミングを行うパラダイム***と説明しましたが、時間と共に状態が変化するもの(データストリーム)はMarble Diagramsという図形で表現されます。以下の画像は最も単純なクリックイベントのストリームです。


<p align="center"><img width="400" alt="スクリーンショット 2016-05-29 16.36.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/ed355a86-d209-2c15-9964-a50708bc91f5.png">
###### 引用: <a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754" target="_blank">The introduction to Reactive Programming you've been missing</a>


横軸が時間の流れで、`○`が送信されるデータになります。画像では、`○`がクリックのイベントを表し、`×`がエラー、`|`が完了処理を表しています。それぞれの関数を定義することによって非同期にキャプチャすることができます。これはAPIなどのコールバック処理をイメージしていただくとわかり易いかと思います。

このストリームは公式に***Observable***と呼ばれ、このObservableを監視することを***subscribe***と言います。

<a href="http://ninjinkun.hatenablog.com/entry/introrxja" target="_blank">【翻訳】あなたが求めていたリアクティブプログラミング入門</a>の記事の何回クリックされたかを表すカウンターストリームを作る例がFRPの本質を表していると思いましたので、紹介していきたいと思います。

先ほどのストリームですが、時間軸に沿って捉えると`[click1, click1, ..]`のようなイベントのリストとして捉えることができます。そして、リストの処理であれば関数型プログラミングでアプローチすることができますね。実際にこのストリームに対してRx系のライブラリでは`map`や`filter`などの関数が用意されています。以下の画像が何回クリックされたかを表すカウンターストリームを作る例です。

<p align="center"><img width="300" alt="687474703a2f2f692e696d6775722e636f6d2f484d47574e4f352e706e67.png" src="https://qiita-image-store.s3.amazonaws.com/0/62451/c5246f78-fc57-f9e0-4880-d782ebb60c2a.png">
###### 引用: <a href="https://gist.github.com/staltz/868e7e9bc2a7b8c1f754" target="_blank">The introduction to Reactive Programming you've been missing</a>

まず、画像で表されている関数はオペレータメソッドと呼ばれ、返り値として処理が施された新しいストリームを返します。返されたストリームは同じくリストとして捉えることのできるストリームなので、再度オペレータメソッドが適応できます。
画像のオペレータメソッドはデモ用なので詳しいことは考えなくてもいいですが、初めにクリックをリストとして積み上げ(`buffer(stream.throttle(250ms))`)、そのストリームのリストをクリック数として変換し(`map`)、さらに返されたストリームに対して、1の場合を無視することで(`filter(x >= 2)`)、最終的な2回以上クリックしたイベントを取得するストリームが手に入っていますね。最後にこのストリームに対して`subscribe`することで望むように反応してくれる処理が書けるわけです。

実際にはこの処理は

```swift
stream
 .buffer(関数)
 .map(関数)
 .filter(関数)
 .subscribe(処理)
```

のような関数型言語のPromiseパターンのようなアプローチができます。このようにRPは関数型言語と親和性が高いものとなっているわけです。これが関数型言語でもあるSwiftにRxが導入された背景にもなっていると考えられます。

これらのストリームとオペレータメソッドは<a href="http://rxmarbles.com/" target="_blank">RxMarbles</a>で視覚的に見ることができるので各オペレータメソッドはここで確認するとわかりやすいと思います。

# <a name="rx_swift">RxSwift
<a href="https://github.com/ReactiveX/RxSwift" target="_blank">RxSwift</a>とは、<a href="http://reactivex.io/">Reactive Extensions</a>をSwift実装として対応させ、Swiftで<a href="https://en.wikipedia.org/wiki/Reactive_programming" target="_blank">RP</a>を実現することができるライブラリです。


## <a name="rx">Reactive Extensions
Reactive Extensions(以降Rx)は2009年に実験的にマイクロソフト社が開発したライブラリで、2011年に正式な製品として認められました。
C#の3.0から導入された<a href="https://msdn.microsoft.com/ja-jp/library/bb397926.aspx" target="_blank">LINQ (Language-Integrated Query)</a>を発展させたものであり、従来では手間がかかる***非同期・イベント処理や時間が関連する処理をLINQの形式で宣言的で簡潔に記述することが可能***になっています。

## <a name="rx_cocoa">RxCocoa
UIKitのクラスをプロパティやイベントをRxが使えるようにWrapしているライブラリで、Viewなどの状態変化やイベントなどを簡単にBindingすることができます。そのためRxSwiftと合わせて使われることが多いです。

## RxSwift導入にあたり

複雑になりがちな非同期・イベント・時間に関する処理を簡潔かつ宣言的に記述できることで、コード量が削減できることや、可読性が高まることがRxSwiftのメリットですが、RPを実現するライブラリはいくつかあります。
その中でRxSwift導入を検討する一番の理由として、Rx自体RxJavaやRxJSを始め様々な言語に対応されていることだと思います。(<a href="http://reactivex.io/languages.html" target="_blank">ReactiveX/Languages</a>) 
そのためRxで使われる概念は他言語でも共通なものが多く、他言語の情報を含めて大量の知見を得られることや他言語でも知見を生かすことができることから学習に対するリターンが大きいと思います。

# <a name="sample">サンプルコードから学ぶ
実際にRxSwiftを用いて、動作確認していきたいと思います。
<a href="https://github.com/ReactiveX/RxSwift/blob/master/Documentation/Examples.md" target="_blank">RxSwiftのExamples</a>の簡単な計算式を例に説明していきます。GoFのオブザーバーパターンを理解していると読みやすいかと思います。
まずは、RxSwiftを使ってない簡単なサンプルです。

```swift
var c = ""
var a = 1
var b = 2

if a + b >= 0 {
    c = "\(a + b) is positive"
}

a = 4
print(c)//"3 is positive"
```
通常だと`a`の変更が反映されずに、宣言時の`a`と`b`の値が反映されて`3 is positive`と出力されます。動的に値が変更される為には、KVOなどのObserverパターン実装などが必要になりますね。今度は、RxSwiftを用いて簡単な式を記述してみます。

```swift
import RxSwift

let a = Variable(1)
let b = Variable(2)

let c = Observable.combineLatest(a.asObservable(), b.asObservable()) { $0 + $1 }
    .filter { $0 >= 0 }
    .map { "\($0) is positive" }
    .subscribeNext { print($0) }//"3 is positive"

a.value = 4//"6 is positive"
b.value = 6//"10 is positive"
b.value = -8// doesn't print anything
```

`a`や`b`の値が変更されると、自動的に`a`と`b`の値が更新された`c`が出力されるようになっています。`filter`や`map`などのオペレータメソッドによって、`a + b`が0以上の場合のみ、`subscribeNext`の処理が施されるようになってますね。それではそれぞれの処理を順次解説していきたいと思います。

SubjectsはObserverパターンでいう監視される側という意味になります。`Variable()`というクラスを用いることで、`a`と`b`の値が監視される対象になっています。

```swift
let a = Variable(1)
let b = Variable(2)
```

`Variable()`は`BehaviorSubject`のWrapperクラスでSubjectsクラスになります。Genericsで定義されているので、`Variable<Int>(1)`のような記述も可能です。`BehaviorSubject`と違って終了処理やエラー処理がないSubjectsクラスなので、単に値をObserveしたい時に使います。続いて、次の処理を見ていきます。


```swift
let c = Observable.combineLatest(a.asObservable(), b.asObservable()) { $0 + $1 }//Observableを返している
    .filter { $0 >= 0 }//combineLatestを参照し、新しいObservableを返す
    .map { "\($0) is positive" }//filterを参照し、新しいObservableを返す
    .subscribeNext { print($0) }//mapを参照し、新しいObservableを返す
```

この処理で使われているオペレータメソッドを見ていきましょう。

### <a href="http://reactivex.io/documentation/operators.html#combining" target="_blank">オペレータメソッド</a>
- <a href="http://reactivex.io/documentation/operators/combinelatest.html" target="_blank">combineLatest</a>
二つのObservable(値)に対して、処理が施された最新のObservable(値)を返す。

- <a href="http://reactivex.io/documentation/operators/filter.html" target="_blank">filter</a>
条件を満たしたObservable(値)のみを返す

- <a href="http://reactivex.io/documentation/operators/map.html" target="_blank">map</a>
処理が施されたObservable(値)を返す

オペレータメソッドが新しいObservableを生成して返し、次のオペレータメソッドがそれを参照し新しいObservableを返しています。Observableはsubscribeできるオブジェクトのことで、それぞれのオペレータメソッドはObservableとObserverの役割を担っています。
このように要素の加工やフィルタリングの処理が順々と行われていく、Promiseパターンのような記述ができるようになっています。これらの処理の流れやObservableについての詳細は<a href="http://hadashia.hatenablog.com/entry/2016/02/23/175736" target="_blank">RxSwift 読んでる</a>の記事がわかりやすいかと思います。

`subscribeNext `は`AnonymousObserver`というObserverを生成していて、一番新しい値を購読するので、最初の宣言時に初期値として`"3 is positive"`が出力されています。
このように、変化した時の振る舞いを記述することで、監視された`a`と`b`の値が更新されたタイミングで、`c`の`subscribeNext`の処理が反応するようになっています。

## RxCocoaを用いたサンプル

UIKitを用いて、DataBindingをする場合の例を紹介していきます。UIKitを用いてRxを実装していく場合にはRxSwiftと合わせて、RxCocoaをimportする必要があります。

```swift
import RxSwift
import RxCocoa
...

@IBOutlet weak var textField: UITextField!
@IBOutlet weak var label: UILabel!

let disposeBag = DisposeBag()
...

textField.rx_text
            .subscribeNext { [unowned self] text in
                self.label.text = text
            }
            .addDisposableTo(disposeBag)
```

<p align="center">![textfield.gif](https://qiita-image-store.s3.amazonaws.com/0/62451/6cd69d8b-fb7c-1d6d-eca4-4a884612e959.gif)

RxCocoaが定義している`rx_text`がObserverの役割を担っていて、`subscribeNext`でBindingしています。
ここの`DisposeBag()`は、deinitのタイミングで`Disposable`を解放させるためのインスタンスで、画面破棄などのタイミングで自動的にDataBindingが解除されるようになっています。`addDisposableTo(disposeBag)`と記述することで、`DisposeBag`がObserverのインスタンスを管理してくれています。

また、`subscribeNext`の戻り値である`Disposable`インスタンスに対して、dispose()を呼び出せば、明示的にDataBindingを解除することもできますが、特に必要がない場合は、`DisposeBag`を用いた自動的なDataBindingの解除がベストだと思います。

以下、UIButtonやUISliderを用いた例になります。基本的な処理はほとんど同じです。

### Buttonのタップ検出

```swift
import RxSwift
import RxCocoa
...

 @IBOutlet weak var button: UIButton!
 let disposeBag = DisposeBag()
...

button.rx_tap
            .subscribeNext { _ in
                print("tapped!")
            }
            .addDisposableTo(disposeBag)
```

<p align="center">![button.gif](https://qiita-image-store.s3.amazonaws.com/0/62451/a0de0756-af8a-690a-293d-5e62c5e11132.gif)


### Sliderの値のBinding

```swift
import RxSwift
import RxCocoa
...

@IBOutlet weak var slider: UISlider!
@IBOutlet weak var label: UILabel!

let disposeBag = DisposeBag()
...

slider.rx_value
            .map { String($0) }
            .subscribeNext { [unowned self] text in
                self.label.text = text
            }
            .addDisposableTo(disposeBag)
```

<p align="center">![slider.gif](https://qiita-image-store.s3.amazonaws.com/0/62451/c6270c0c-1961-2661-c029-1ed7df1a7bc2.gif)

# おわりに

Reactiveからライブラリの事まで簡単にまとめましたが、ReactiveやRxの事を深く理解するにはまだまだ学ぶことが多く、学習コストは高いと感じました。
しかし、概念の事を学ばなくてもRxSwiftなどのライブラリ使えるので、実際にライブラリを使ったり、サンプルコードを読んで行きながら学ぶことが重要かなと思いました。これからも、RxやReactiveのまとめを記事にしていけたらなと思います。


# 参考

## RxSwift
- [ReactiveX/RxSwift](https://github.com/ReactiveX/RxSwift)
- [[初心者]RxSwiftの道標[入門]]
(http://qiita.com/nakailand/items/8b54dc9b4b39b0809c57)
- [#RxSwift_Sansan 今流行のRxをswiftで学ぶ！ RxSwift勉強会 ＠ Sansanに行ってきたまとめ](http://blog.mogmet.com/rxswift-sansan/)
- [タコさんブログ / RxSwift 入門 その１](http://tiny-wing.hatenablog.com/entry/2016/01/02/161322)
- [タコさんブログ / RxSwift 入門 その２](http://tiny-wing.hatenablog.com/entry/2016/01/11/172915)
- [RxSwift で UIKit を扱う基本](http://qiita.com/usamik26/items/2bbd0b8d304ab42b2279)
- [RxSwiftでデータバインド -補足編-](http://niwaka.hateblo.jp/entry/2015/10/28/210850)

## Reactive Extensions
- [第1回　Reactive Extensionsの概要と利用方法](http://www.atmarkit.co.jp/fdotnet/introrx/introrx_01/introrx_01_01.html)
- [ReactiveX](http://reactivex.io/)
- [Rx入門](http://blog.xin9le.net/entry/rx-intro)
- [関数型プログラマのための Rx 入門（前編）](http://okapies.hateblo.jp/entry/2015/03/04/031148)

## Reactive
- [Reactiveは哲学だ！ with Swift](http://dev.classmethod.jp/smartphone/iphone/reactive-with-swift/)
- [The Reactive Manifesto](http://www.reactivemanifesto.org/)
- [Q. （関数型）リアクティブプログラミングとは何ですか？](http://postd.cc/what-is-functional-reactive-programming/)
- [2015年に備えて知っておきたいリアクティブアーキテクチャの潮流](http://qiita.com/hirokidaichi/items/9c1d862099c2e12f5b0f)
- [やさしいFunctional reactive programming（概要編）](http://maoe.hatenadiary.jp/entry/20100109/1263059731)
- [2010-12-26 なぜリアクティブプログラミングは重要か。](http://d.hatena.ne.jp/pokarim/20101226)
- [注目を集めるリアクティブプログラミング](https://www.infoq.com/jp/news/2013/09/reactive-programming-emerging)
- [【翻訳】あなたが求めていたリアクティブプログラミング入門](http://ninjinkun.hatenablog.com/entry/introrxja)
- [RxSwift 読んでる](http://hadashia.hatenablog.com/entry/2016/02/23/175736)