【Swift】RxSwift入門 ①

はじめに

突然ですが、RxSwift は難しい。。

何が難しいって、まず聞き慣れない言葉が多く登場するし、それらがいつ何のために使われるのかもわかりづらいし、いろんなサイトのサンプルソースを見ても、パッと見でどう動いているのかが掴みづらい。

周りのデキる人たちは「RxSwiftは良い……」と口々に申されているけど、実際RxSwiftの何がいいのか? どんなところで使えばいいのか? それもよくわからない。

ある程度理解が進み、ある程度コードを書いて感触を掴まないと、そもそもこれを使う意義すら見えてこない。

RxSwift(に限らず、Reactive Programming全般)のハードルの高さはそういったところにあるのではないかと思います。

そこでこの記事では、極力わかりやすい言葉とコードでRxSwiftの全体像が掴めて、ひとまず仕事で使っていけるようになることを目指して説明していきたいと思います。

RxSwiftをはじめ、Reactive Programming初学者の方の助けとなれば幸いです。

RxSwiftとは?

RxSwiftとは、ReactiveX のSwift版です。

ReactiveX?

本家サイトから引用します。

ReactiveX is a library for composing asynchronous and event-based programs by using observable sequences.

It extends the observer pattern to support sequences of data and/or events and adds operators that allow you to compose sequences together declaratively while abstracting away concerns about things like low-level threading, synchronization, thread-safety, concurrent data structures, and non-blocking I/O.

reactivex.io

これによると、つまりはReactiveXとは、「Observerパターンを拡張し、データやイベントのSequenceをサポートして、low-level threadingやsynchronization、thread-safety等々を気にすることなく宣言的にコードを書くことができる」ライブラリのようです。

これではわかりづらいので、もう少し噛み砕きます。

Observerパターン?

Observerパターンとは、簡単に言うと「ある人が何かしたら、そのことを知りたい人たちに教えてあげる処理方式」のことです。
そしてこの言葉が出てくるということは、「API通信が終わったら、その結果を元に何かしたい」とか「ボタンがタップされたら何かしたい」など、非同期処理(とコールバック関数)やUIイベント(とイベントハンドラ)などの処理に関係している、ということになります。

Observerパターンについては別な記事にまとめたので、合わせてご覧いただければと思います。
とは言え、ここでは「Subject」= 何かしらのアクションを起こす人、「Observer」= Subjectの起こしたアクションに合わせて別の何かをする人、という2つの単語と役割が理解できていれば大丈夫です。

Sequence?

Sequenceとは何でしょう?
Sequenceとは、「“順番に並んだデータや手続き”のこと、または順番に並んだそれらを並んだ順番通りに随時処理していく“方式”」のことを指します。
そのまんま、配列をfor文で回して、各要素を順に処理していくイメージです。

それをサポートすると言っているので、「データやイベントが何かの順番に従って発生し、それらを順次、逐一処理に掛けることができる」とひとまず理解できます。

非同期処理にまつわるあれこれ

low-level threadingやsynchronization、thread-safety等々というのは?
マルチスレッドによる非同期並列処理を行いたいと考えた時、スレッド作成のためのコードを書くことはもちろん、複数のスレッド間で競合やデッドロック等が起こらないようにするための同期制御や、あるリソースへの同時アクセスによる整合性破壊を防ぐための排他制御、「通信はサブスレッドだけどUI処理はメインスレッドじゃないとダメ」みたいな制約によるスレッドの切り替え・管理など、実現のためにはいろいろと考慮しなければならないこと、書かなければならないコードが多数存在します。

これは慣れない人だと制御に抜けがあってバグを生んでしまったり、必然的にコード量が増えて可読性やメンテナンス性に暗い影を落としたりしてしまいます。

ReactiveXさんは、そうした厄介なことを引き受けてこちらの負担を軽減してくれるみたいです。

宣言的?

宣言的にコードを書くことができる
宣言的ってなんでしょう?

「Declarative Programming(宣言型プログラミング)」という言葉があります。
また、その対となるものとして「Imperative Programming(命令型プログラミング)」という言葉もあります。
これらの違いをざっくり言うと、前者は「何がしたいか(What)」を記述するプログラムで、後者は「どうしたいか(How)」を記述するプログラムとされています。

例えば、宣言型の代表にSQLがあります。
SQLでは

SELECT id, title
FROM books
WHERE publish_date >= '20191122'

のように、「idとtitleを選出します」「booksテーブルから取ります」「発行日が2019/11/22以降のものに絞ります」とやりたいことを宣言していくように記述します。
ただやりたいことを書いているだけなので、やらんとしていることがすぐ理解できますよね。
これがDeclarative Programmingです。

一方で、命令型の代表にC言語があります。
C言語では

int total = 0;
for (int i = 1; i <= 10; i++) {
  total += i;
}
printf("total = %d", total);

のように、1行ずつただひたすら命令を記述していきます。
↑のような単純な処理ならいいのですが、これが複雑なものになってくると比例して「このコードはつまり何がしたいのだろう?」と理解が及ばなくなる度合いが強くなっていきます。
きちんとした“意義あるコメント”が書かれていなければ、そこにあるのはただの地獄です。
これがImperative Programmingです。

とは言え、命令型にも宣言型のように書く方法があります。
その1つが関数化です。
組み込みのものでも自作のものでも、きちんとしたネーミングとパッケージングがされた関数を使用することで、

int total = sum_range(1, 10);
write_to_file("value.dat", total);
printf("total = %d", total);

のように、「ああ、1から10までの合計を出して、ファイルに出力して、画面にも出しているんだな」とやっていることを理解しやすくすることができます。
(もちろん、各関数の中身はザッツ命令型のコードになっているでしょうけど)

長くなりましたが、これがつまりは「宣言的にコードを書く」の意味であり、ReactiveXでそれが可能だということは、SQLのように、あるいは宣言型的命令型プログラミング(なにそれ)のように、「やりたいことを書いていくだけ」を実現してくれるものが用意されている、ということになるのではないでしょうか。

つまりは?

まとめると、つまりReactiveXとは・・・

Observerパターンが使われる非同期処理やUIのイベント処理などを、
意図した手順で処理できるSequenceな形で、
かつ誰にも理解しやすい宣言的な書き方で、
スレッドの同期制御やリソースの排他制御やなんかの辛い処理を自分で書くことなく、
実装することのできるライブラリ。

もっと簡単に言うと、

「最高のライブラリ」

です。

さあ、「RxSwiftは良い……」の気配がしてまいりました。

おわりに

第2回に続きます。

次回は簡単なサンプルコードを書いて、RxSwiftの処理の流れについて書きたいと思います。