ご存知の通りクライアントサイドでのユーザ体験はよりリッチなものになってきています。ユーザ体験がリッチになればより複雑な状態管理が求められます。iOS開発においてもこの複雑さに対応するためのアーキテクチャやその実装について長く議論されてきました。
一方で、ウェブフロントエンドでもFluxやReduxの登場で、ページ内での状態管理やアプリケーション全体を通してのグローバルな状態管理をどうするのかなど、非常に複雑な状態管理をわかりやすく記述するための設計が確立しつつあります。Fluxでは状態変更に必要な責務を適切に分割し、わかりやすく宣言できるようにしたこと、流れが一方向であることが、読みやすさに大きく貢献しているように思います。さらに、Reduxではページ間での状態共有や変更の依存関係をうまく表現するための仕組みを実現しています。
Jeon 氏はReactorKitを作った理由として以下の3つを上げました。
より具体的な実装を「Instagramのプロフィール画面にあるフォローボタンをタップしてフォロー状態にする」という状態変化を例に紹介されていました。
さて、Jeon 氏はもう少し詳細なユースケースについても述べられていましたが、他の発表者の内容と重複する部分もあるので割愛します。詳しくはスライドをご確認ください。
さて、テストは非常に重要なパートです。ほとんどのライブラリは、テストコードを書く方法を考慮されていなければならず、なければ導入は困難です。もちろん、ReactorKitはその方法を提供しています。さらに、Jeon 氏はより明確にテストの対象や方法について示しています。これはReactorKitの魅力の一つです。
まず、テスト対象は何でしょうか。Jeon 氏はViewおよびReactorで以下のことをテストするべきだということを述べました。
さて、具体的にどのようにテストをする必要があるでしょうか。Jeon 氏はこの点についても具体的な方法を述べています。まず、Reactorにはstubというプロパティが用意されており、このプロパティを通して簡単にスタブを実現できるようになっています。このスタブの機能を利用することで、Reactorのstateに任意のStateを設定し、必要なActionを送ることができます。さらにどんなActionを受け取ったのかを記録することができます。これでテストの準備が十分であることがわかります。
まず、ReactorKitの利点についてです。大きく2つあり、1つは強力な規約があること、もう一つは軽量であることと述べられていました。
多くのアーキテクチャではアーキテクチャを理解して、正しい実装に落とすことは容易ではありません。これらは具体的な規約を持たず、チームやプロジェクトに依存するためです。一方Fluxライクなアーキテクチャを実現するReactorKitでは柔軟性がありつつ、非常に強力な規約があることが強みです。そのため、導入してすぐにコードを書くことができます。
続いて、1.5人月規模のプロジェクトで導入したときに悩んだポイントとそのアプローチについてです。以下の5つの疑問について述べられていました。それでは一つずつ見ていきます。
例えば、編集画面で編集を中断しようとして編集内容が失われるような場合、「Are sure?」のようなAlertを表示することが一般的ですが、このようなAlertは誰が行うのでしょうか?Alertの画面遷移ではあるので、VIewレイヤでしょうか?菅原 レイヤだと述べています。これを行う理由として、AlertのActionを型安全にできることを上げています。菅原 氏はこの考え方に賛否がありそうだとも付け加えていますが、ユーザの操作を伴う副作用もActionストリーム内の反応(React)の1つに過ぎないと考えることができると主張されていました。
この発表では、ソフトウェアアーキテクチャとは何かについてを述べられ、Fluxの立ち位置を確認したのち、ReactorKitの良さについて語られました。
「アーキテクチャとは、システムの重要な構成のことであり、システムのコンポーネントや互いの関係、環境、その設計と展望を導く考え方を実現するものです。」
非常に抽象度が高いですが、なんとなく伝わってきます。さらに、Peter 氏の記事で述べられていることを簡単にまとめられていました。以下のとおりです。
多賀谷 氏は特に最後の3つについて重点的に説明されていました。
「ステークホルダーの複数の相反する要求の均衡を保つ」にいては、社内外のステークホルダーが沢山存在し、そして同時に彼らの要求をうまくバランスするためにアーキテクチャが機能し、そしてそれが重要であることを述べています。
次に、「取り巻く環境に依存する」では、会社の環境、例えば、株価やDAU、コードベースの古さや量、多くの新しい機能や多くのエンジニアなど、様々な変数に依存することを説明しています。
永島 氏は、ReactorKitがシンプルというだけでなく、強力であることも伝えています。実際の実装例として3つのケースを上げました。
まず、「ブックマークの状態を表示する」についてです。このケースでは、画面が読み込まれた時に リクエストを実行し、その結果を表示します。
さて、次にこのブックマークの状態を他のViewコンポーネントでも表示したいケースについてです。Visit Appでは、募集の一覧画面でもブックマークの状態が表示されているため、ここにも状態を反映します。一般に、詳細ページと一覧ページで状態を共有したいというケースは数多く存在するかと思います。こういったケースでは、共有するストリームを作成します。ストリームへの流し込みはRepositoryレイヤで行います。次に受け取りたいViewコンポーネントに対応するReactorのtransform関数を利用します。transform関数ではmutationのストリームにマージすることができるため、共有のストリームからMutationに変換してマージします。これだけで、状態を簡単に共有することができます。
さて、早速導入から始めます。CocoaPodsでインストールします。また、注意点としては、オフィシャルにCarthage対応されていない点です。
ここで八谷 さんは、いくつか躓いたケースについてご紹介されていました。
まず、「アクションが発行されない」という問題です。実は今までの流れで抜けているパートがあります。それは、View Controllerに作成したReactorをセットするというパートです。ここで重要なのは、そのView Controllerの外側でセットするという点です。
八谷 氏は全体としてコードが読みやすくなる点を指摘しつつ、特に以下の特徴をあげられていました。
さて、本題に入りましょう。StyleShare社で実践されているTDDでどのようにテストを書いているのかについてステップバイステップで説明をされていました。
StyleShareは、韓国ファッション&ビューティー情報を見ることのできるiOS Appを提供しています。Fig. の通り、Beautyのタブでは美容情報が一覧で表示されています。このタブを実装することを例として説明しています。
それでは、isRefreshingを定義しましょう。Fig. 6.4の通りに変更すると、今度はグリーンになっていることが確認できます。
次は、「初期状態でコンテンツが空であること」を期待します。つまりbeautyFeedEventsが空であることを検証するコードを追記します。さらにプロダクトコードでstateとinitialStateを定義することでこのコードをパスすることができます。
次にfetchのアクションを呼ぶことで適切なコレクションがセットされることを期待します。ここでServiceクラスを作成し、そのモックを作成します。モックは先程紹介したStubberを利用します。最後にmutate関数とreduce関数を実装すればテストをパスすることができます。
さて、発表内容の解説は以上です。もうすでにReactorKitを利用されている方は、より踏み込んだ現場の知見を知ることができたでしょうか?また、初めての方にはReactorKitの魅力を感じて導入してみたいと感じてもらえたでしょうか?本記事を通してReactorKitの理解の一助となれば幸いです。最後になりましたが、お読みいただきありがとうございます。そして、一緒にコミュニティを盛り上げていきましょう!