Link
Embed
Share
Beginning
This slide
Copy link URL
Copy link URL
Copy iframe embed code
Copy iframe embed code
Copy javascript embed code
Copy javascript embed code
Share
Tweet
Share
Tweet
Slide 1
Slide 1 text
AWAの フルリニューアルを支えた アーキテクチャ 2019/03/26 CA.apk #7 Keita Kagurazaka
Slide 2
Slide 2 text
AWAについて ● 定額制音楽ストリーミングサービス ● 競合にはSpotify, Apple Music, YouTube Music, LINE MUSICなどなど ● Androidアプリは2019年1月24日にフルリ ニューアルをリリース
Slide 3
Slide 3 text
なぜリニューアルしたのか ● リリースしてから3年以上にわたって機能を付け足し続けた結 果、複雑でユーザの理解が難しいプロダクトに ○ アプリを初めて使ったユーザが何をすればいいかわからない ● 開発速度を優先した結果、メンテナンスが困難なソフトウェア に ○ Fat Activity、上げられないライブラリのバージョン、作成時代によって 違う設計 etc.
Slide 4
Slide 4 text
リニューアルの目的 ● すべての機能を再整理し、新規ユーザでもわかりやすいUIに 変更、UXを最大化する ● これまで溜め込んだ技術的負債を返済し、今後の開発速度を 向上させる
Slide 5
Slide 5 text
リアーキテクチャ
Slide 6
Slide 6 text
そもそもアーキテクチャって なんのためにあるの?
Slide 7
Slide 7 text
アーキテクチャは何のためにあるか ● すべてのアーキテクチャは本質的には制約 ● 開発者ができることを減らすことで、誤りを防ぐ ● 間違えないなら制約は緩くてよい
Slide 8
Slide 8 text
アーキテクチャは何のためにあるか ● すべてのアーキテクチャは本質的には制約 ● 開発者ができることを減らすことで、誤りを防ぐ ● 間違えないなら制約は緩くてよい どのくらい自由度を犠牲にすべきかは チームとプロダクトに強く依存する
Slide 9
Slide 9 text
チームとアーキテクチャ (1) ● チームの人数が多ければ多いほど、自由度は制限したほうが 良い ○ コミュニケーションコストは人数に対して指数関数的に増加する ○ 小チームに分けるという選択肢は有力 ○ 採用も見据えて考える
Slide 10
Slide 10 text
チームとアーキテクチャ (2) ● 技術習得度が高くないメンバーが含まれる場合、自由度は制 限したほうが良い ○ 設計方針を事前レビューしてから実装してもらうくらいなら最初から枠 組みがあったほうが良い ○ 技術習得度が高いメンバーとペア / モブプログラミングをする場合は 自由度を高くできる
Slide 11
Slide 11 text
プロダクトとアーキテクチャ ● プロダクトが巨大で複雑な場合、自由度は制限したほうが良 い ○ 人数の話と基本的には同じ ○ 機能で分割するのは有力 (Androidならばmulti-module) ○ ドメインの複雑さは向き合うしかない
Slide 12
Slide 12 text
AWAのAndroidチームとアーキテクチャ ● チームは4人と小規模 ● 技術習得度は全員高く、必要な議論を躊躇わないタイプ ● プロダクトは巨大で複雑 (167画面とかある) ● 拠点が渋谷と福岡で分かれている
Slide 13
Slide 13 text
設計方針 ● レイヤードアーキテクチャを採用し、各処理をどの階層に置く かまで合意する ● ルール化したほうが良さそうならば都度議論する ● 重要度が高く、複雑な音楽再生とダウンロードについてはより 制約をきつくする ● 必要なら福岡にいく
Slide 14
Slide 14 text
設計方針 ● レイヤードアーキテクチャを採用し、各処理をどの階層に置く かまで合意する ● ルール化したほうが良さそうならば都度議論する ● 重要度が高く、複雑な音楽再生とダウンロードについてはより 制約をきつくする ● 必要なら福岡にいく ビデオ通話を常時接続する
Slide 15
Slide 15 text
方針は定まった
Slide 16
Slide 16 text
実現したいこと ● ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する ● 音楽が再生できる画面では再生状況をリアクティブに表示した い
Slide 17
Slide 17 text
実現したいこと ● ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する ● 音楽が再生できる画面では再生状況をリアクティブに表示した い CQRSアーキテクチャを採用
Slide 18
Slide 18 text
CQRS (コマンドクエリ責務分離) ● システム全体を更新系と参照系に分離する ● 更新系の操作は値を返さない ● 参照系はシステムを更新しない (副作用なし) ● 詳しくはこちら https://speakerdeck.com/kkagurazaka/cqrs-architecture-on-android
Slide 19
Slide 19 text
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository Data Command ワーカースレッドで実行
Slide 20
Slide 20 text
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository Data Command ● Viewからのイベントを受けてUseCaseをキック する
Slide 21
Slide 21 text
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository Data Command ● DataCommandをオーケストレーションして処 理を行う ● 戻り値はCompletable
Slide 22
Slide 22 text
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository Data Command ● APIからデータを取得してDBに書き込む ● 扱うEntityごとにクラスが分かれる ● 戻り値はCompletable
Slide 23
Slide 23 text
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository Data Command ● Entityを保存するだけ ● トランザクションを管理する ● 戻り値はUnit
Slide 24
Slide 24 text
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository Data Command ● 消えてもいいキャッシュはRealm ● 重要なデータはSQLite (Room) ● 設定系はSharedPreferences ● プロセスを跨がせないデータはon-memory
Slide 25
Slide 25 text
参照系 View ViewModel UseCase DB Data Query Repository Data Query RealmのためにUIスレッドで実行 Repository
Slide 26
Slide 26 text
参照系 View ViewModel UseCase DB Data Query Repository Data Query Repository ● DBの変更を検知してRxJavaのストリームに変 換する ● 戻り値はFlowable ● Realmの場合はRealmResults
Slide 27
Slide 27 text
参照系 View ViewModel UseCase DB Data Query Repository Data Query Repository ● 必要があればEntityを分解した値にしたり、 distinctUntilChangedしたり ● ごく一部のキャッシュしない参照のためにAPIを 叩くこともある
Slide 28
Slide 28 text
参照系 View ViewModel UseCase DB Data Query Repository Data Query Repository ● DataQueryをオーケストレーションして、Viewに 必要な情報を作る
Slide 29
Slide 29 text
参照系 View ViewModel UseCase DB Data Query Repository Data Query Repository ● UseCaseをobserveしてObservableFieldに詰 め、DataBindingでViewをリアクティブに更新 する
Slide 30
Slide 30 text
実現したいこと (再掲) ● ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する ● 音楽が再生できる画面では再生状況をリアクティブに表示した い
Slide 31
Slide 31 text
実現したいこと (再掲) ● ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する ● 音楽が再生できる画面では再生状況をリアクティブに表示した い キャッシュを書いてから画面に表示する作り バックグラウンドでデータが書き換わると画面もリアクティブに 変化する
Slide 32
Slide 32 text
制限を緩めたところ ● 本来CQRSでは更新系と参照系でEntityのクラスを分けるが、 重要度が高い再生キューとダウンロード以外は分けなかった ○ 参照系で更新操作をしないようにしよう、で事足りた ● 細かいコーディング規約は定めず、コミット前にコードフォー マットすることだけにした ○ たとえばapply派とalso派が混在しているが別に問題はなかった
Slide 33
Slide 33 text
実際やってみてどうだったか
Slide 34
Slide 34 text
リアーキテクチャしてみて ● どこに何を書いたら良いか迷わなくなった ● 責務が分かれたため、テストが書きやすくなった ● データフローがわかりやすくなったことによってメンテナンス性 が向上した ● パフォーマンスには注意
Slide 35
Slide 35 text
まとめ ● AndroidアプリをCQRSアーキテクチャでフルリニューアルした ● 不具合をほとんど出さずにすばやく開発できるようになった ● ベストなアーキテクチャはチームとプロダクトによって違う
Slide 36
Slide 36 text
Thanks!