はじめに
先日サイバーエージェントが主催するSwiftの勉強会に参加しました。
今回はその時の内容を簡単に紹介します。
会場
株式会社サイバーエージェント クリエイティブラウンジ
発表内容
- Reduxを活用したiOSアプリアーキテクチャ
- gRPCとSwift
- Tips to ios app analytics
- FRESH!配信アプリで採用した事、しなかった事
- 72時間ホンネTV、クライアントサイドも負荷対策?!
Reduxを活用したiOSアプリアーキテクチャ
登壇者は杉上 洋平氏
Twitter: https://twitter.com/susieyy
Reduxの特徴、Swiftで使用する場合(ReSwiftの実装例)、ReSwiftでの非同期処理(実装例)、viewの差分更新について発表がありました。
資料: https://speakerdeck.com/susieyy/reduxrxwohuo-yong-sitaapuriakitekutiya
Reduxとは
Reduxは、ReactJSが扱うUIのstate(状態)を管理をするためのフレームワークです。
Reactではstateの管理するデータフローにFluxを提案していますが、ReduxはFluxの概念を拡張してより扱いやすく設計されています。
参考: https://qiita.com/kiita312/items/49a1f03445b19cf407b7
Reduxの3つの原則
- single source of truth(アプリ全体の状態を1つのオブジェクトツリーで表現)
- State is read-only(状態を変更するには必ずアクションを発行する)
- Mutations are written as pure function(状態変更は副作用がない純粋関数を用い、状態を直接変更せず、新しい状態を作って返す)
副作用:外的要因(DBアクセスなど)が無いこと。
要点
Viewと状態を完全に分離しています。
Viewのロジックはその瞬間のアプリ内のすべての状態が一意であることが保証されているので、その瞬間の状態に対して非同期の介入がない。
よって、非同期実行中の中間状態を意識する必要がないため、シングルスレッドだけで動作している感覚でロジックが書けます。
また、イミュータブルと純粋関数を活用して徹底的に副作用を分離しているので、他の(MVC等)アーキテクチャとは異なる設計思想であり、シンプルで堅牢でかつ可読性の高いコーディングが可能となります。
さらに、イミュータブルが扱えて関数型志向なSwiftと相性が良いです。
Reduxを何で実装するか
下記の理由によりReSwiftを採用します。
- 他のライブラリと比べて一番有名
- 関数やクロージャを中心に設計されており、実装がとてもきれい
- リリース頻度がよく、ISSUEも活発である
ReSwiftでの副作用(非同期処理)
例ではActionController内で非同期通信を行っています。
ただし、これではActionControllerが純粋関数ではなくなりテストがしにくくなります。
Redux(JS)ではActionとStateの中間にMiddlewareというレイヤーを設けてそこで副作用を処理しています。
これをSwiftに置き換えた場合の実装例を紹介していました。
また、副作用をMiddlewareに任せることでそれ以外の部分を純粋関数で実装できるので、テストが用意になるメリットが有ります。
Viewの差分更新
iOSにはReactのVirtual DomのようなViewの差分更新を行う機能がありません。
そこで、IGListKitというライブラリが紹介されていました。
IGListKitの特徴は下記のとおりです。
- UICollectionViewをベースにできている
- データはいろいろな型の要素を含む1次元配列
- データの要素の方でコンポーネントを分岐する
- 実装はObjectiv-C(プロトコル準拠のためNSObjectの継承が必要)
gRPCとSwift
登壇者は林 眞司氏
GitHub: https://github.com/shin8484
Protocol BuffersとgRPCの説明について発表がありました。
(ブログ執筆時点で資料が公開されていないため、簡単な紹介となります)
Protocol Buffersとは
Protocol Buffers(プロトコルバッファー)はインタフェース定義言語 (IDL) で構造を定義する通信や永続化での利用を目的としたシリアライズフォーマットであり、Googleにより開発されている。
オリジナルのGoogle実装はC++、Java、Pythonによるものであり、フリーソフトウェアとしてオープンソースライセンスで公開されている。
参考: https://ja.wikipedia.org/wiki/Protocol_Buffers
同じようなものとしてJSONがありますが、あちらと比較するとデータ量が少なく高速である反面、学習コストがかかります。
gRPCとは
gRPC は、RPC (Remote Procedure Call) を実現するためにGoogleが開発したプロトコルの1つです。
Protocol Buffers を使ってデータをシリアライズし、高速な通信を実現できる点が特長です。
参考: https://qiita.com/oohira/items/63b5ccb2bf1a913659d6
Tips to ios app analytics
登壇者は志甫 侑紀氏
GitHub: https://github.com/shihochan
Twitter: https://twitter.com/shihochandesu
ユーザ分析をする上での課題、ツール(Google Tag Manager)、実例について発表がありました。
資料: https://speakerdeck.com/shihochan/tips-to-ios-app-analytics
課題
課題としては下記の3つがあげられます。
- 誰に何をどこで確認してもらうか(ツール選定、仕様選定、評価基準)
- 分析者とエンジニアのコミュニケーション(何をどうやって計測・分析するか)
- 細かいトラッキング仕様はコードを汚くする(iOSはリリースまでに審査がある)
分析者とエンジニアのコミュニケーションでは両者が同じツール用いて仕様を確認できる状態が望ましいです。
そこで、Google Tag Managerを利用することでツールを統一し、さらに管理を分析者に移譲することができました。
Google Tag Manager
Google Tag Managerには下記の特徴があります。
- 複数プロダクトの計測タグを発行可能(Firebase Analytics, Google Analytics, DoubleClick, etc)
- 設定コンソールがドキュメントになる(設定の管理と更新を分析者に移譲できる)
- アプリのリリース無しに(一部の)計測設定を更新できる
- Firebaseに統合(使いやすい)
分析を用いた改善の実例
例ではR25というアプリでユーザの読了率を上げるために行ったことの発表がありました。
FRESH!配信アプリで採用した事、しなかった事
登壇者は青山 遼氏
GitHub: https://github.com/ra1028
Twitter: https://twitter.com/ra1028fe5
FRESH!配信アプリ開発において採用した(しなかった)フレームワーク等について発表がありました。
資料: https://speakerdeck.com/ra1028/fresh-pei-xin-apuridecai-yong-sitashi-sinakatutashi
VueFlux
VueFluxは登壇者の青山氏が開発したフレームワークで、Flux(Redux)を採用する上での下記の問題を解決しています。
- Stateの中央集中によるつらみ
- 型情報がスポイルされるたりOptionalな情報が多いことによるcast、unwrapの嵐…
登壇者曰く、「画面とStateが1:1のMulti-Store構成でStateがMutableと、ユーザの多いReduxの逆を行ったもののiOSでのFluxとMVVMの辛さをうまく丸める感覚で使いやすい」とのこと。
GitHub: https://github.com/ra1028/VueFlux
ライブラリ
・ライブラリの選定としては枯れたものを選ぶ事が多いようです。
「通信系などの動作や起こりうるバグの全容が掴めないものは、単純にユーザが多いほうがニッチなバグ修正が入っている」ため。
また、既存に良いものがなければ(時間に余裕があれば)自作することで対応するそうです。
SVGアイコンリソース
SVGファイルを使うための方法として「FontCustom」が紹介されていました。
FontCustomはSVGファイル群からTTFファイルにマッピングするツールです。
GitHub: https://github.com/FontCustom/fontcustom
XcodeGen
XcodeGenはYAMLファイルに記述した設定からxcodeprojectを生成するツールです。
これによりxcodeproject(pbxproj)をgitignoreすることができ、コンフリクトを無くせるなどのメリットがありますが、Derived Data(キャッシュ)不整合でビルドエラーが発生する等の問題が発生したため一時導入が見送りになったそうです。
GitHub: https://github.com/yonaskolb/XcodeGen
Danger
DangerはPullRequestのルールを形式化してCIからGitHubのMachineアカウントを通じて自動的にレビューさせるツールです。
設定ファイル(Dangerfile)にはRuby、JavaScript、Swiftなどが使えます。
GitHub: https://github.com/danger/danger
72時間ホンネTV、クライアントサイドも負荷対策?!
登壇者は石川 諒氏()
GitHub: https://github.com/rinov
Twitter: https://twitter.com/rinov0321
AbemaTVでの負荷対策を行った経緯と実際の対応について発表がありました。
(ブログ執筆時点で資料が公開されていないため、簡単な紹介となります)
負荷対策
大きく2つの対策が施されました。
1つ目はプレイリストのCDN化です。
AbemaTVはリクエスト数が多いう結果がわかり、特にプレイリストのリクエストが多かったことからプレイリストをCDNにキャッシュさせました。
それに合わせてユーザ情報をクライアントアプリから送るように修正しました(もともとはサーバ側で判定していたが、CDN化したことによってそのままでは判定できなくなったため)
すると、今度は番組が切り替わるタイミングでアクセスが高くなったので、番組表のリクエストをランダムに1〜5秒ディレイさせるようにしました。
2つ目は視聴数を取得するAPIのポーリング感覚の可変化です。
通常は7秒間隔でポーリングしていましたが、視聴数が1,000を超えるとk表記になるため1,000〜1,999の範囲ではポーリングが無駄になります。
そこで、通常時はポーリング間隔を14秒にしつつ、1,000以上になったら間隔を70秒に広げました。
これらの対策により大幅な負荷軽減を達成しました。
さいごに
今回はどの発表も内容が非常に濃かったと思います。
次も機会があれば参加したいと思います。