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

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

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

CA.apk #7

Keita Kagurazaka

March 26, 2019
Tweet

More Decks by Keita Kagurazaka

Other Decks in Programming

Transcript

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

    View Slide

  2. AWAについて
    ● 定額制音楽ストリーミングサービス
    ● 競合にはSpotify, Apple Music, YouTube
    Music, LINE MUSICなどなど
    ● Androidアプリは2019年1月24日にフルリ
    ニューアルをリリース

    View Slide

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

    ○ Fat Activity、上げられないライブラリのバージョン、作成時代によって
    違う設計 etc.

    View Slide

  4. リニューアルの目的
    ● すべての機能を再整理し、新規ユーザでもわかりやすいUIに
    変更、UXを最大化する
    ● これまで溜め込んだ技術的負債を返済し、今後の開発速度を
    向上させる

    View Slide

  5. リアーキテクチャ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  10. チームとアーキテクチャ (2)
    ● 技術習得度が高くないメンバーが含まれる場合、自由度は制
    限したほうが良い
    ○ 設計方針を事前レビューしてから実装してもらうくらいなら最初から枠
    組みがあったほうが良い
    ○ 技術習得度が高いメンバーとペア / モブプログラミングをする場合は
    自由度を高くできる

    View Slide

  11. プロダクトとアーキテクチャ
    ● プロダクトが巨大で複雑な場合、自由度は制限したほうが良

    ○ 人数の話と基本的には同じ
    ○ 機能で分割するのは有力 (Androidならばmulti-module)
    ○ ドメインの複雑さは向き合うしかない

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  15. 方針は定まった

    View Slide

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

    View Slide

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

    CQRSアーキテクチャを採用

    View Slide

  18. CQRS (コマンドクエリ責務分離)
    ● システム全体を更新系と参照系に分離する
    ● 更新系の操作は値を返さない
    ● 参照系はシステムを更新しない (副作用なし)
    ● 詳しくはこちら https://speakerdeck.com/kkagurazaka/cqrs-architecture-on-android

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  29. 参照系
    View ViewModel UseCase DB
    Data
    Query
    Repository
    Data
    Query
    Repository
    ● UseCaseをobserveしてObservableFieldに詰
    め、DataBindingでViewをリアクティブに更新
    する

    View Slide

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

    View Slide

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

    キャッシュを書いてから画面に表示する作り
    バックグラウンドでデータが書き換わると画面もリアクティブに
    変化する

    View Slide

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

    View Slide

  33. 実際やってみてどうだったか

    View Slide

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

    View Slide

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

    View Slide

  36. Thanks!

    View Slide