Upgrade to Pro — share decks privately, control downloads, hide ads and more …

設計にみるAWA Androidアプリのこれまでとこれから

設計にみるAWA Androidアプリのこれまでとこれから

AWA Androidアプリの設計に関する過去と未来の話。

51599b694b52e34258f54a98257036b9?s=128

Ryota Takemoto

March 12, 2018
Tweet

More Decks by Ryota Takemoto

Other Decks in Programming

Transcript

  1. 設計にみる AWA Androidアプリの これまでとこれから

  2. 新家 亮太 @AWA @r21nomi r21nomi Android / Creative Coding / Anime

  3. 本⽇話すこと

  4. • これまでの設計 • その問題点 • これからの設計

  5. これまでの設計

  6. これまでの設計 ー ⽴ち上げ期 ー

  7. • 2014.10〜 • Androidエンジニア 1 ~ 4⼈ • いわゆるMVC •

    テストほぼゼロ
  8. Model • DB, APIアクセス • ビジネスロジック Activity / Fragment •

    プレゼンテーションロジック • ビジネスロジック
  9. Model • DB, APIアクセス • ビジネスロジック Activity / Fragment •

    プレゼンテーションロジック • ビジネスロジック
  10. Model • DB, APIアクセス • ビジネスロジック Activity / Fragment •

    プレゼンテーションロジック • ビジネスロジック ビジネスロジックを書く層が必要
  11. Model • DB, APIアクセス • ビジネスロジック Activity / Fragment •

    プレゼンテーションロジック • ビジネスロジック
  12. Model •DB, APIアクセス •ビジネスロジック Activity / Fragment • プレゼンテーションロジック •

    ビジネスロジック
  13. Model •DB, APIアクセス •ビジネスロジック Activity / Fragment • プレゼンテーションロジック •

    ビジネスロジック Modelの責務分割が必要
  14. • ビジネスロジックを書く層をつくる • Modelの責務を分割

  15. これまでの設計 ー 設計改善期 ー

  16. • 2016.4〜 • Androidエンジニア 5⼈ • Clean Architecture Like •

    data層のテスト充実
  17. Model Activity / Fragment Before

  18. DbClient / ApiClient Activity / Fragment Model UseCase Model Activity

    / Fragment Before After
  19. DbClient / ApiClient • DB, APIアクセス Activity / Fragment •

    プレゼンテーションロジック Model • DbClient / ApiClientの操作 UseCase • ビジネスロジック
  20. DbClient / ApiClient • DB, APIアクセス Activity / Fragment •

    プレゼンテーションロジック Model • DbClient / ApiClientの操作 UseCase • ビジネスロジック ビジネスロジックを書く層 ◎ Modelの責務を分割 ◎
  21. DbClient / ApiClient • DB, APIアクセス Activity / Fragment •

    プレゼンテーションロジック Model • DbClient / ApiClientの操作 UseCase • ビジネスロジック だが、まだまだ問題が
  22. • 依然として巨⼤なActivity • ⼿続き型の処理多数 • 役割を失ったBase class • 修正困難な巨⼤クラス

  23. 結局、何が問題だったのか?

  24. 設計の擦り合わせをしていなかった

  25. → どこに何を書くべきかがバラバラ → 1クラスの責務が⼤きくなりすぎる → ⼀貫性のないコード 設計の擦り合わせをしていなかった

  26. v2構想

  27. ちゃんと設計の議論をして1から作る

  28. • リーダビリティ シンプルに テストが書ける • テスタビリティ • メンテナビリティ 変更に強い 実装時に迷わない

  29. 設計は可視化しよう

  30. 新しい設計 ※3/12時点

  31. • レイヤードアーキテクチャ + MVVM • CQRS

  32. 依存⽅向 app data ui domain data

  33. ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase

    CommandUseCase
  34. ViewModel CommandUseCase QueryUseCase ApiClient Repository Activity DataCommand DataQuery UI 画⾯データの管理

    永続化データのI/F データ更新・取得処理の組み⽴て ビジネスロジック
  35. ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase

    CommandUseCase
  36. ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase

    CommandUseCase
  37. ApiClient • Retrofitインターフェース Repository

  38. ApiClient • Retrofitインターフェース Repository • ローカルデータソースのインターフェース • DB, Pref, File,

    Memory • 使う側はデータソースの種類を意識しない
  39. APIはRepositoryではない?

  40. “リポジトリを使う側からは、 ドメインモデルがあたかもメモリ上にコレク ションとして存在しているかのように⾒える” Martin Fowler

  41. Repositoryを使う側はデータソースを 意識すべきではない

  42. APIからデータを取得し、DBに保存 interface Repository<T> { fun fetch(): Single<T> fun save(data: T)

    } repository.fetch() .doOnSuccess { repository.save(it) }
  43. ← データソース(API)を意識してる ← 保存先は知らない interface Repository<T> { fun fetch(): Single<T>

    fun save(data: T) } repository.fetch() .doOnSuccess { repository.save(it) } repository.fetch() repository.save(it) APIからデータを取得し、DBに保存
  44. interface Repository<T> { fun save(data: T) } apiClient.fetch() .doOnSuccess {

    repository.save(it) } ← APIからの取得を意識する apiClient.fetch() repository.save(it) ← 保存先は知らない APIからデータを取得し、DBに保存
  45. ApiClient • APIのインターフェース Repository • ローカルデータソースのインターフェース

  46. ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase

    CommandUseCase
  47. ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase

    CommandUseCase
  48. ViewModel DataQuery DataCommand ApiClient Repository Activity 依存⽅向 app data QueryUseCase

    CommandUseCase Command? Query?
  49. CQRS Command Query Responsibility Segregation

  50. 更新処理 → Command 取得処理 → Query

  51. 更新処理 → Command 取得処理 → Query • データの変更はしない • 値を返すだけ

    • データを変更する • 値は返さない
  52. 「取得 × 更新」が複雑性を⽣む

  53. ViewModel UseCase Single 更新・取得

  54. ViewModel UseCase Single CommandUseCase QueryUseCase Completable Flowable ViewModel 更新・取得 取得

    更新
  55. CommandからQueryを分離し、 複雑性を緩和

  56. データの流れ

  57. ViewModel CommandUseCase ApiClient Repository Activity データの流れ app data QueryUseCase DataCommand

    DataQuery
  58. ViewModel CommandUseCase ApiClient Repository Activity データの流れ app data QueryUseCase DataCommand

    DataQuery
  59. ViewModel CommandUseCase ApiClient Repository Activity データの流れ app data QueryUseCase DataCommand

    DataQuery
  60. データの流れが単⼀⽅向に

  61. まとめ

  62. • レイヤー分けをし、責務を明確に • 更新と取得を分け、複雑性を緩和 • 曖昧にせずちゃんと議論して決める • 設計は可視化する 設計 進め⽅

  63. Thank You @r21nomi r21nomi