Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
AWAのフルリニューアルを支えたアーキテクチャ
Search
Keita Kagurazaka
March 26, 2019
Programming
1
810
AWAのフルリニューアルを支えたアーキテクチャ
CA.apk #7
Keita Kagurazaka
March 26, 2019
Tweet
Share
More Decks by Keita Kagurazaka
See All by Keita Kagurazaka
SELECT FOR UPDATEの話
kkagurazaka
0
290
Mobileアプリのアーキテクチャ設計法
kkagurazaka
2
1.3k
原理から完全理解するDagger Hilt Migration
kkagurazaka
1
1.7k
今後のJetpackでAndroid開発はこう変わる!
kkagurazaka
16
5.9k
外部SDKのViewにマスク処理をする方法と罠
kkagurazaka
0
870
CQRS Architecture on Android
kkagurazaka
7
2.8k
suspending functionの裏側
kkagurazaka
3
420
coroutinesで非同期ページネーション
kkagurazaka
1
600
async/awaitで快適非同期ライフ
kkagurazaka
4
1.8k
Other Decks in Programming
See All in Programming
テストコードのガイドライン 〜作成から運用まで〜
riku929hr
1
170
menu基盤チームによるGoogle Cloudの活用事例~Application Integration, Cloud Tasks編~
yoshifumi_ishikura
0
110
Haze - Real time background blurring
chrisbanes
1
510
開発者とQAの越境で自動テストが増える開発プロセスを実現する
92thunder
1
180
CSC305 Lecture 25
javiergs
PRO
0
130
HTTP compression in PHP and Symfony apps
dunglas
2
1.7k
Recoilを剥がしている話
kirik
5
6.6k
fs2-io を試してたらバグを見つけて直した話
chencmd
0
230
数十万行のプロジェクトを Scala 2から3に完全移行した
xuwei_k
0
270
선언형 UI에서의 상태관리
l2hyunwoo
0
150
フロントエンドのディレクトリ構成どうしてる? Feature-Sliced Design 導入体験談
osakatechlab
8
4.1k
複雑な仕様に立ち向かうアーキテクチャ
myohei
0
170
Featured
See All Featured
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
28
9.1k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
44
9.3k
We Have a Design System, Now What?
morganepeng
51
7.3k
Automating Front-end Workflow
addyosmani
1366
200k
Agile that works and the tools we love
rasmusluckow
328
21k
Faster Mobile Websites
deanohume
305
30k
GitHub's CSS Performance
jonrohan
1030
460k
JavaScript: Past, Present, and Future - NDC Porto 2020
reverentgeek
47
5.1k
Side Projects
sachag
452
42k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
2
290
Documentation Writing (for coders)
carmenintech
66
4.5k
Why You Should Never Use an ORM
jnunemaker
PRO
54
9.1k
Transcript
AWAの フルリニューアルを支えた アーキテクチャ 2019/03/26 CA.apk #7 Keita Kagurazaka
AWAについて • 定額制音楽ストリーミングサービス • 競合にはSpotify, Apple Music, YouTube Music, LINE
MUSICなどなど • Androidアプリは2019年1月24日にフルリ ニューアルをリリース
なぜリニューアルしたのか • リリースしてから3年以上にわたって機能を付け足し続けた結 果、複雑でユーザの理解が難しいプロダクトに ◦ アプリを初めて使ったユーザが何をすればいいかわからない • 開発速度を優先した結果、メンテナンスが困難なソフトウェア に ◦
Fat Activity、上げられないライブラリのバージョン、作成時代によって 違う設計 etc.
リニューアルの目的 • すべての機能を再整理し、新規ユーザでもわかりやすいUIに 変更、UXを最大化する • これまで溜め込んだ技術的負債を返済し、今後の開発速度を 向上させる
リアーキテクチャ
そもそもアーキテクチャって なんのためにあるの?
アーキテクチャは何のためにあるか • すべてのアーキテクチャは本質的には制約 • 開発者ができることを減らすことで、誤りを防ぐ • 間違えないなら制約は緩くてよい
アーキテクチャは何のためにあるか • すべてのアーキテクチャは本質的には制約 • 開発者ができることを減らすことで、誤りを防ぐ • 間違えないなら制約は緩くてよい どのくらい自由度を犠牲にすべきかは チームとプロダクトに強く依存する
チームとアーキテクチャ (1) • チームの人数が多ければ多いほど、自由度は制限したほうが 良い ◦ コミュニケーションコストは人数に対して指数関数的に増加する ◦ 小チームに分けるという選択肢は有力 ◦
採用も見据えて考える
チームとアーキテクチャ (2) • 技術習得度が高くないメンバーが含まれる場合、自由度は制 限したほうが良い ◦ 設計方針を事前レビューしてから実装してもらうくらいなら最初から枠 組みがあったほうが良い ◦ 技術習得度が高いメンバーとペア
/ モブプログラミングをする場合は 自由度を高くできる
プロダクトとアーキテクチャ • プロダクトが巨大で複雑な場合、自由度は制限したほうが良 い ◦ 人数の話と基本的には同じ ◦ 機能で分割するのは有力 (Androidならばmulti-module) ◦
ドメインの複雑さは向き合うしかない
AWAのAndroidチームとアーキテクチャ • チームは4人と小規模 • 技術習得度は全員高く、必要な議論を躊躇わないタイプ • プロダクトは巨大で複雑 (167画面とかある) • 拠点が渋谷と福岡で分かれている
設計方針 • レイヤードアーキテクチャを採用し、各処理をどの階層に置く かまで合意する • ルール化したほうが良さそうならば都度議論する • 重要度が高く、複雑な音楽再生とダウンロードについてはより 制約をきつくする •
必要なら福岡にいく
設計方針 • レイヤードアーキテクチャを採用し、各処理をどの階層に置く かまで合意する • ルール化したほうが良さそうならば都度議論する • 重要度が高く、複雑な音楽再生とダウンロードについてはより 制約をきつくする •
必要なら福岡にいく ビデオ通話を常時接続する
方針は定まった
実現したいこと • ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する • 音楽が再生できる画面では再生状況をリアクティブに表示した い
実現したいこと • ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する • 音楽が再生できる画面では再生状況をリアクティブに表示した い CQRSアーキテクチャを採用
CQRS (コマンドクエリ責務分離) • システム全体を更新系と参照系に分離する • 更新系の操作は値を返さない • 参照系はシステムを更新しない (副作用なし) •
詳しくはこちら https://speakerdeck.com/kkagurazaka/cqrs-architecture-on-android
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository
Data Command ワーカースレッドで実行
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository
Data Command • Viewからのイベントを受けてUseCaseをキック する
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository
Data Command • DataCommandをオーケストレーションして処 理を行う • 戻り値はCompletable
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository
Data Command • APIからデータを取得してDBに書き込む • 扱うEntityごとにクラスが分かれる • 戻り値はCompletable
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository
Data Command • Entityを保存するだけ • トランザクションを管理する • 戻り値はUnit
更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository
Data Command • 消えてもいいキャッシュはRealm • 重要なデータはSQLite (Room) • 設定系はSharedPreferences • プロセスを跨がせないデータはon-memory
参照系 View ViewModel UseCase DB Data Query Repository Data Query
RealmのためにUIスレッドで実行 Repository
参照系 View ViewModel UseCase DB Data Query Repository Data Query
Repository • DBの変更を検知してRxJavaのストリームに変 換する • 戻り値はFlowable<Entity> • Realmの場合はRealmResults<Entity>
参照系 View ViewModel UseCase DB Data Query Repository Data Query
Repository • 必要があればEntityを分解した値にしたり、 distinctUntilChangedしたり • ごく一部のキャッシュしない参照のためにAPIを 叩くこともある
参照系 View ViewModel UseCase DB Data Query Repository Data Query
Repository • DataQueryをオーケストレーションして、Viewに 必要な情報を作る
参照系 View ViewModel UseCase DB Data Query Repository Data Query
Repository • UseCaseをobserveしてObservableFieldに詰 め、DataBindingでViewをリアクティブに更新 する
実現したいこと (再掲) • ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する • 音楽が再生できる画面では再生状況をリアクティブに表示した い
実現したいこと (再掲) • ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する • 音楽が再生できる画面では再生状況をリアクティブに表示した い キャッシュを書いてから画面に表示する作り バックグラウンドでデータが書き換わると画面もリアクティブに
変化する
制限を緩めたところ • 本来CQRSでは更新系と参照系でEntityのクラスを分けるが、 重要度が高い再生キューとダウンロード以外は分けなかった ◦ 参照系で更新操作をしないようにしよう、で事足りた • 細かいコーディング規約は定めず、コミット前にコードフォー マットすることだけにした ◦
たとえばapply派とalso派が混在しているが別に問題はなかった
実際やってみてどうだったか
リアーキテクチャしてみて • どこに何を書いたら良いか迷わなくなった • 責務が分かれたため、テストが書きやすくなった • データフローがわかりやすくなったことによってメンテナンス性 が向上した • パフォーマンスには注意
まとめ • AndroidアプリをCQRSアーキテクチャでフルリニューアルした • 不具合をほとんど出さずにすばやく開発できるようになった • ベストなアーキテクチャはチームとプロダクトによって違う
Thanks!