設計にみるAWA Androidアプリのこれまでとこれから
by
Ryota Takemoto
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 Androidアプリの これまでとこれから
Slide 2
Slide 2 text
新家 亮太 @AWA @r21nomi r21nomi Android / Creative Coding / Anime
Slide 3
Slide 3 text
本⽇話すこと
Slide 4
Slide 4 text
• これまでの設計 • その問題点 • これからの設計
Slide 5
Slide 5 text
これまでの設計
Slide 6
Slide 6 text
これまでの設計 ー ⽴ち上げ期 ー
Slide 7
Slide 7 text
• 2014.10〜 • Androidエンジニア 1 ~ 4⼈ • いわゆるMVC • テストほぼゼロ
Slide 8
Slide 8 text
Model • DB, APIアクセス • ビジネスロジック Activity / Fragment • プレゼンテーションロジック • ビジネスロジック
Slide 9
Slide 9 text
Model • DB, APIアクセス • ビジネスロジック Activity / Fragment • プレゼンテーションロジック • ビジネスロジック
Slide 10
Slide 10 text
Model • DB, APIアクセス • ビジネスロジック Activity / Fragment • プレゼンテーションロジック • ビジネスロジック ビジネスロジックを書く層が必要
Slide 11
Slide 11 text
Model • DB, APIアクセス • ビジネスロジック Activity / Fragment • プレゼンテーションロジック • ビジネスロジック
Slide 12
Slide 12 text
Model •DB, APIアクセス •ビジネスロジック Activity / Fragment • プレゼンテーションロジック • ビジネスロジック
Slide 13
Slide 13 text
Model •DB, APIアクセス •ビジネスロジック Activity / Fragment • プレゼンテーションロジック • ビジネスロジック Modelの責務分割が必要
Slide 14
Slide 14 text
• ビジネスロジックを書く層をつくる • Modelの責務を分割
Slide 15
Slide 15 text
これまでの設計 ー 設計改善期 ー
Slide 16
Slide 16 text
• 2016.4〜 • Androidエンジニア 5⼈ • Clean Architecture Like • data層のテスト充実
Slide 17
Slide 17 text
Model Activity / Fragment Before
Slide 18
Slide 18 text
DbClient / ApiClient Activity / Fragment Model UseCase Model Activity / Fragment Before After
Slide 19
Slide 19 text
DbClient / ApiClient • DB, APIアクセス Activity / Fragment • プレゼンテーションロジック Model • DbClient / ApiClientの操作 UseCase • ビジネスロジック
Slide 20
Slide 20 text
DbClient / ApiClient • DB, APIアクセス Activity / Fragment • プレゼンテーションロジック Model • DbClient / ApiClientの操作 UseCase • ビジネスロジック ビジネスロジックを書く層 ◎ Modelの責務を分割 ◎
Slide 21
Slide 21 text
DbClient / ApiClient • DB, APIアクセス Activity / Fragment • プレゼンテーションロジック Model • DbClient / ApiClientの操作 UseCase • ビジネスロジック だが、まだまだ問題が
Slide 22
Slide 22 text
• 依然として巨⼤なActivity • ⼿続き型の処理多数 • 役割を失ったBase class • 修正困難な巨⼤クラス
Slide 23
Slide 23 text
結局、何が問題だったのか?
Slide 24
Slide 24 text
設計の擦り合わせをしていなかった
Slide 25
Slide 25 text
→ どこに何を書くべきかがバラバラ → 1クラスの責務が⼤きくなりすぎる → ⼀貫性のないコード 設計の擦り合わせをしていなかった
Slide 26
Slide 26 text
v2構想
Slide 27
Slide 27 text
ちゃんと設計の議論をして1から作る
Slide 28
Slide 28 text
• リーダビリティ シンプルに テストが書ける • テスタビリティ • メンテナビリティ 変更に強い 実装時に迷わない
Slide 29
Slide 29 text
設計は可視化しよう
Slide 30
Slide 30 text
新しい設計 ※3/12時点
Slide 31
Slide 31 text
• レイヤードアーキテクチャ + MVVM • CQRS
Slide 32
Slide 32 text
依存⽅向 app data ui domain data
Slide 33
Slide 33 text
ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase CommandUseCase
Slide 34
Slide 34 text
ViewModel CommandUseCase QueryUseCase ApiClient Repository Activity DataCommand DataQuery UI 画⾯データの管理 永続化データのI/F データ更新・取得処理の組み⽴て ビジネスロジック
Slide 35
Slide 35 text
ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase CommandUseCase
Slide 36
Slide 36 text
ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase CommandUseCase
Slide 37
Slide 37 text
ApiClient • Retrofitインターフェース Repository
Slide 38
Slide 38 text
ApiClient • Retrofitインターフェース Repository • ローカルデータソースのインターフェース • DB, Pref, File, Memory • 使う側はデータソースの種類を意識しない
Slide 39
Slide 39 text
APIはRepositoryではない?
Slide 40
Slide 40 text
“リポジトリを使う側からは、 ドメインモデルがあたかもメモリ上にコレク ションとして存在しているかのように⾒える” Martin Fowler
Slide 41
Slide 41 text
Repositoryを使う側はデータソースを 意識すべきではない
Slide 42
Slide 42 text
APIからデータを取得し、DBに保存 interface Repository { fun fetch(): Single fun save(data: T) } repository.fetch() .doOnSuccess { repository.save(it) }
Slide 43
Slide 43 text
← データソース(API)を意識してる ← 保存先は知らない interface Repository { fun fetch(): Single fun save(data: T) } repository.fetch() .doOnSuccess { repository.save(it) } repository.fetch() repository.save(it) APIからデータを取得し、DBに保存
Slide 44
Slide 44 text
interface Repository { fun save(data: T) } apiClient.fetch() .doOnSuccess { repository.save(it) } ← APIからの取得を意識する apiClient.fetch() repository.save(it) ← 保存先は知らない APIからデータを取得し、DBに保存
Slide 45
Slide 45 text
ApiClient • APIのインターフェース Repository • ローカルデータソースのインターフェース
Slide 46
Slide 46 text
ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase CommandUseCase
Slide 47
Slide 47 text
ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase CommandUseCase
Slide 48
Slide 48 text
ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase CommandUseCase Command? Query?
Slide 49
Slide 49 text
CQRS Command Query Responsibility Segregation
Slide 50
Slide 50 text
更新処理 → Command 取得処理 → Query
Slide 51
Slide 51 text
更新処理 → Command 取得処理 → Query • データの変更はしない • 値を返すだけ • データを変更する • 値は返さない
Slide 52
Slide 52 text
「取得 × 更新」が複雑性を⽣む
Slide 53
Slide 53 text
ViewModel UseCase Single 更新・取得
Slide 54
Slide 54 text
ViewModel UseCase Single CommandUseCase QueryUseCase Completable Flowable ViewModel 更新・取得 取得 更新
Slide 55
Slide 55 text
CommandからQueryを分離し、 複雑性を緩和
Slide 56
Slide 56 text
データの流れ
Slide 57
Slide 57 text
ViewModel CommandUseCase ApiClient Repository Activity データの流れ app data QueryUseCase DataCommand DataQuery
Slide 58
Slide 58 text
ViewModel CommandUseCase ApiClient Repository Activity データの流れ app data QueryUseCase DataCommand DataQuery
Slide 59
Slide 59 text
ViewModel CommandUseCase ApiClient Repository Activity データの流れ app data QueryUseCase DataCommand DataQuery
Slide 60
Slide 60 text
データの流れが単⼀⽅向に
Slide 61
Slide 61 text
まとめ
Slide 62
Slide 62 text
• レイヤー分けをし、責務を明確に • 更新と取得を分け、複雑性を緩和 • 曖昧にせずちゃんと議論して決める • 設計は可視化する 設計 進め⽅
Slide 63
Slide 63 text
Thank You @r21nomi r21nomi