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
850
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
360
Mobileアプリのアーキテクチャ設計法
kkagurazaka
2
1.4k
原理から完全理解するDagger Hilt Migration
kkagurazaka
1
1.8k
今後のJetpackでAndroid開発はこう変わる!
kkagurazaka
16
6k
外部SDKのViewにマスク処理をする方法と罠
kkagurazaka
0
920
CQRS Architecture on Android
kkagurazaka
7
2.9k
suspending functionの裏側
kkagurazaka
3
430
coroutinesで非同期ページネーション
kkagurazaka
1
630
async/awaitで快適非同期ライフ
kkagurazaka
4
1.8k
Other Decks in Programming
See All in Programming
アーキテクトと美学 / Architecture and Aesthetics
nrslib
12
3.1k
英語文法から学ぶ、クリーンな設計の秘訣
newnomad
1
270
RailsでCQRS/ESをやってみたきづき
suzukimar
2
1.5k
英語 × の私が、生成AIの力を借りて、OSSに初コントリビュートした話
personabb
0
120
보일러플레이트 코드가 진짜 나쁜 건가요?
gaeun5744
0
370
AHC 044 混合整数計画ソルバー解法
kiri8128
0
300
아직도 SOLID 를 '글'로만 알고 계신가요?
sh1mj1
0
360
Defying Front-End Inertia: Inertia.js on Rails
skryukov
0
220
AtCoder Heuristic First-step Vol.1 講義スライド
terryu16
2
1k
DataStoreをテストする
mkeeda
0
150
RCPと宣言型ポリシーについてのお話し
kokitamura
2
150
Go1.24で testing.B.Loopが爆誕
kuro_kurorrr
0
170
Featured
See All Featured
KATA
mclloyd
29
14k
4 Signs Your Business is Dying
shpigford
183
22k
Into the Great Unknown - MozCon
thekraken
36
1.7k
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Designing for Performance
lara
606
69k
We Have a Design System, Now What?
morganepeng
51
7.5k
Imperfection Machines: The Place of Print at Facebook
scottboms
267
13k
The Art of Programming - Codeland 2020
erikaheidi
53
13k
Java REST API Framework Comparison - PWX 2021
mraible
29
8.5k
The Cost Of JavaScript in 2023
addyosmani
48
7.6k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
118
51k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
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!