AWAのフルリニューアルを支えたアーキテクチャ

 AWAのフルリニューアルを支えたアーキテクチャ

CA.apk #7

0f8842fabcd31a6c9007ddcd648247db?s=128

Keita Kagurazaka

March 26, 2019
Tweet

Transcript

  1. AWAの フルリニューアルを支えた アーキテクチャ 2019/03/26 CA.apk #7 Keita Kagurazaka

  2. AWAについて • 定額制音楽ストリーミングサービス • 競合にはSpotify, Apple Music, YouTube Music, LINE

    MUSICなどなど • Androidアプリは2019年1月24日にフルリ ニューアルをリリース
  3. なぜリニューアルしたのか • リリースしてから3年以上にわたって機能を付け足し続けた結 果、複雑でユーザの理解が難しいプロダクトに ◦ アプリを初めて使ったユーザが何をすればいいかわからない • 開発速度を優先した結果、メンテナンスが困難なソフトウェア に ◦

    Fat Activity、上げられないライブラリのバージョン、作成時代によって 違う設計 etc.
  4. リニューアルの目的 • すべての機能を再整理し、新規ユーザでもわかりやすいUIに 変更、UXを最大化する • これまで溜め込んだ技術的負債を返済し、今後の開発速度を 向上させる

  5. リアーキテクチャ

  6. そもそもアーキテクチャって なんのためにあるの?

  7. アーキテクチャは何のためにあるか • すべてのアーキテクチャは本質的には制約 • 開発者ができることを減らすことで、誤りを防ぐ • 間違えないなら制約は緩くてよい

  8. アーキテクチャは何のためにあるか • すべてのアーキテクチャは本質的には制約 • 開発者ができることを減らすことで、誤りを防ぐ • 間違えないなら制約は緩くてよい どのくらい自由度を犠牲にすべきかは チームとプロダクトに強く依存する

  9. チームとアーキテクチャ (1) • チームの人数が多ければ多いほど、自由度は制限したほうが 良い ◦ コミュニケーションコストは人数に対して指数関数的に増加する ◦ 小チームに分けるという選択肢は有力 ◦

    採用も見据えて考える
  10. チームとアーキテクチャ (2) • 技術習得度が高くないメンバーが含まれる場合、自由度は制 限したほうが良い ◦ 設計方針を事前レビューしてから実装してもらうくらいなら最初から枠 組みがあったほうが良い ◦ 技術習得度が高いメンバーとペア

    / モブプログラミングをする場合は 自由度を高くできる
  11. プロダクトとアーキテクチャ • プロダクトが巨大で複雑な場合、自由度は制限したほうが良 い ◦ 人数の話と基本的には同じ ◦ 機能で分割するのは有力 (Androidならばmulti-module) ◦

    ドメインの複雑さは向き合うしかない
  12. AWAのAndroidチームとアーキテクチャ • チームは4人と小規模 • 技術習得度は全員高く、必要な議論を躊躇わないタイプ • プロダクトは巨大で複雑 (167画面とかある) • 拠点が渋谷と福岡で分かれている

  13. 設計方針 • レイヤードアーキテクチャを採用し、各処理をどの階層に置く かまで合意する • ルール化したほうが良さそうならば都度議論する • 重要度が高く、複雑な音楽再生とダウンロードについてはより 制約をきつくする •

    必要なら福岡にいく
  14. 設計方針 • レイヤードアーキテクチャを採用し、各処理をどの階層に置く かまで合意する • ルール化したほうが良さそうならば都度議論する • 重要度が高く、複雑な音楽再生とダウンロードについてはより 制約をきつくする •

    必要なら福岡にいく ビデオ通話を常時接続する
  15. 方針は定まった

  16. 実現したいこと • ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する • 音楽が再生できる画面では再生状況をリアクティブに表示した い

  17. 実現したいこと • ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する • 音楽が再生できる画面では再生状況をリアクティブに表示した い CQRSアーキテクチャを採用

  18. CQRS (コマンドクエリ責務分離) • システム全体を更新系と参照系に分離する • 更新系の操作は値を返さない • 参照系はシステムを更新しない (副作用なし) •

    詳しくはこちら https://speakerdeck.com/kkagurazaka/cqrs-architecture-on-android
  19. 更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository

    Data Command ワーカースレッドで実行
  20. 更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository

    Data Command • Viewからのイベントを受けてUseCaseをキック する
  21. 更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository

    Data Command • DataCommandをオーケストレーションして処 理を行う • 戻り値はCompletable
  22. 更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository

    Data Command • APIからデータを取得してDBに書き込む • 扱うEntityごとにクラスが分かれる • 戻り値はCompletable
  23. 更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository

    Data Command • Entityを保存するだけ • トランザクションを管理する • 戻り値はUnit
  24. 更新系 View ViewModel UseCase ApiClient DB Data Command ApiClient Repository

    Data Command • 消えてもいいキャッシュはRealm • 重要なデータはSQLite (Room) • 設定系はSharedPreferences • プロセスを跨がせないデータはon-memory
  25. 参照系 View ViewModel UseCase DB Data Query Repository Data Query

    RealmのためにUIスレッドで実行 Repository
  26. 参照系 View ViewModel UseCase DB Data Query Repository Data Query

    Repository • DBの変更を検知してRxJavaのストリームに変 換する • 戻り値はFlowable<Entity> • Realmの場合はRealmResults<Entity>
  27. 参照系 View ViewModel UseCase DB Data Query Repository Data Query

    Repository • 必要があればEntityを分解した値にしたり、 distinctUntilChangedしたり • ごく一部のキャッシュしない参照のためにAPIを 叩くこともある
  28. 参照系 View ViewModel UseCase DB Data Query Repository Data Query

    Repository • DataQueryをオーケストレーションして、Viewに 必要な情報を作る
  29. 参照系 View ViewModel UseCase DB Data Query Repository Data Query

    Repository • UseCaseをobserveしてObservableFieldに詰 め、DataBindingでViewをリアクティブに更新 する
  30. 実現したいこと (再掲) • ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する • 音楽が再生できる画面では再生状況をリアクティブに表示した い

  31. 実現したいこと (再掲) • ユーザに対してローディング表示をなるべく見せないようにす るため、キャッシュを最大限に活用する • 音楽が再生できる画面では再生状況をリアクティブに表示した い キャッシュを書いてから画面に表示する作り バックグラウンドでデータが書き換わると画面もリアクティブに

    変化する
  32. 制限を緩めたところ • 本来CQRSでは更新系と参照系でEntityのクラスを分けるが、 重要度が高い再生キューとダウンロード以外は分けなかった ◦ 参照系で更新操作をしないようにしよう、で事足りた • 細かいコーディング規約は定めず、コミット前にコードフォー マットすることだけにした ◦

    たとえばapply派とalso派が混在しているが別に問題はなかった
  33. 実際やってみてどうだったか

  34. リアーキテクチャしてみて • どこに何を書いたら良いか迷わなくなった • 責務が分かれたため、テストが書きやすくなった • データフローがわかりやすくなったことによってメンテナンス性 が向上した • パフォーマンスには注意

  35. まとめ • AndroidアプリをCQRSアーキテクチャでフルリニューアルした • 不具合をほとんど出さずにすばやく開発できるようになった • ベストなアーキテクチャはチームとプロダクトによって違う

  36. Thanks!