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

Baby steps to improve architecture in Study Sapuri Android

chiiia12
February 05, 2020

Baby steps to improve architecture in Study Sapuri Android

chiiia12

February 05, 2020
Tweet

More Decks by chiiia12

Other Decks in Programming

Transcript

  1. #sapurimeetup Baby steps to improve architecture In Study Sapuri Android

    @chiiia12 Study Sapuri/Quipper Product Meetup #4
  2. #sapurimeetup @chiiia12 / 横尾千明 2 • Mobile Engineer at Quipper

    ◦ 2018.4 Study Sapuri Android team join ◦ Quipper Product Team Blogの運営 • 2015年新卒でエンジニアとしてリクルート入社 ◦ お小遣い稼ぎサービスでサーバーサイド開発 ◦ 人材領域でAndroidアプリ開発 Baby steps to improve architecture In Study Sapuri Android
  3. #sapurimeetup Agenda | 01 02 03 04 Androidチームの現状と技術的課題 どのように実践していくか Try

    & Error 振り返り・まとめ 4 Baby steps to improve architecture In Study Sapuri Android
  4. #sapurimeetup • 小中高大学受験生向けの学習アプリ • ユーザータイプ: 5タイプ • ソースコード:135,125行 • 現ソースコードでの開発:5年以上

    • 歴史と複雑さを持つアプリ Study Sapuri について 7 Baby steps to improve architecture In Study Sapuri Android
  5. #sapurimeetup 手をつけられていなかった課題感 • 2017年から開発停止しているGreenDaoがまだ使われている • 時代ごとに違うアーキテクチャ ◦ MVPとMVVMが混ざっている状態 • Kotlin率

    10% • データ操作をすべてまとめる1800行のFatクラス • RxJava部分で頻発する不具合の調査に時間がかかる ◦ 今のメンバーのスキルセットと合っていない技術選定 8 Baby steps to improve architecture In Study Sapuri Android
  6. #sapurimeetup New architecture : to be • データ操作を担当するFatクラス -> DataごとのRepository作成

    • JavaからKotlinへ • MVP → MVVMへ ◦ EventBusからLiveDataへ ◦ RxJavaからCoroutineへ • GreenDao → Room 9 Baby steps to improve architecture In Study Sapuri Android
  7. #sapurimeetup New architecture : to be • データ操作を担当するFatクラス -> DataごとのRepository作成

    • JavaからKotlinへ • MVP → MVVMへ ◦ EventBusからLiveDataへ ◦ RxJavaからCoroutineへ • GreenDao → Room 13 Baby steps to improve architecture In Study Sapuri Android
  8. #sapurimeetup 技術選定のポイント • Google公式/推奨のものを基本的に採用 ◦ MVVM, LiveData, Kotlin etc... •

    チームメンバーに馴染みがあるか ◦ RxJavaは難しい… • 学ぶのにモチベーションがあがるか ◦ Kotlin, Coroutine etc... 14 Baby steps to improve architecture In Study Sapuri Android
  9. #sapurimeetup Before 15 … … Fragment.java Activity.java Presenter.java ModelManager.java DB(GreenDao)

    Network EventBusで通知 Baby steps to improve architecture In Study Sapuri Android
  10. #sapurimeetup After 16 … … Fragment.kt Activity.kt ViewModel.kt Repository.kt DB(Room)/Network

    LiveDataで通知 … LiveDataで通知 Baby steps to improve architecture In Study Sapuri Android
  11. #sapurimeetup タスクへの分解 17 Migrate GreenDao to Room - GreenDaoを廃止しRoomを採用 -

    データごとのDaoを作成しモデル層をまとめる Fatク ラスを廃止 アプリ全体 Convert to Kotlin - JavaからKotlinへ変換 各画面 Migrate to MVVM - ViewModelの追加 - EventBusからLiveDataへ変更 - RxJavaからCoroutineへ変更 各画面 Baby steps to improve architecture In Study Sapuri Android
  12. #sapurimeetup ビジネス案件を止めずに改善を行う戦略 18 • タスクを特性によって分解 ◦ 一気に進めないといけないもの ◦ 大規模案件の開発に影響のあるもの ◦

    複数画面に影響のあるもの ◦ 独立して進められるもの • 先にやるもの、後でも問題ないものに分解しスケジュール化 Baby steps to improve architecture In Study Sapuri Android
  13. #sapurimeetup ビジネス案件を止めずに改善を行う戦略 19 • Phase1: Migrate GreenDao to Room ◦

    小さくリリースができないのでまとまった時間を使って進める • Phase2: 大規模案件に影響する画面のKotlin化、MVVM化 ◦ 見通しの良い状態で大規模案件を始めたい • Phase3: その他の画面のKotlin化、MVVM化 ◦ 誰でも独立して進められる。期限の制約がない ◦ MVVM化は最低ViewModelの追加とLiveDataへの導入は行う Baby steps to improve architecture In Study Sapuri Android
  14. #sapurimeetup Try & Error 03 20 Baby steps to improve

    architecture In Study Sapuri Android
  15. #sapurimeetup 試行錯誤した点 21 • スコープの調整 • 新導入したLibraryでのベストプラクティス探し ◦ Kotlin Coroutine

    ◦ LiveData • 開発プロセスの改善 ◦ コードレビュー ◦ タスクのアサインと知見共有 Baby steps to improve architecture In Study Sapuri Android
  16. #sapurimeetup Kotlin Coroutine 23 • [Before] ExceptionHandlerを使ったエラーハンドリング val scope =

    viewModelScope + CoroutineExceptionHandler { _ , _-> Timber.d("failure clickDebugButton ") } var count = 0 fun clickDebugButton() = scope.launch { count++ if (count % 2 == 0) { throw AssertionError("count%2 is 0") } Timber.d("success clickDebugButton") } ViewModel.kt Baby steps to improve architecture In Study Sapuri Android
  17. #sapurimeetup Kotlin Coroutine 24 期待値は success と failure が交互に出る clickDebugButton:

    success clickDebugButton clickDebugButton: failure clickDebugButton clickDebugButton: success clickDebugButton clickDebugButton: failure clickDebugButton Logcat Baby steps to improve architecture In Study Sapuri Android
  18. #sapurimeetup Kotlin Coroutine 25 実際は一度エラーが出るとcatchし続けてしまう clickDebugButton: success clickDebugButton CoroutineExceptionHandler: failure

    clickDebugButton CoroutineExceptionHandler: failure clickDebugButton CoroutineExceptionHandler: failure clickDebugButton Logcat Baby steps to improve architecture In Study Sapuri Android ※ version 1.2.1
  19. #sapurimeetup Kotlin Coroutine 26 • [After] runCatching, onFailureを使ったハンドリングに変更 var count

    = 0 fun clickDebugButton() = viewModelScope.launch { runCatching { count++ if (count % 2 == 0) { throw AssertionError("count%2 is 0") } }.onSuccess { Timber.d("success clickDebugButton") }.onFailure { Timber.d("failure clickDebugButton") } } ViewModel.kt Baby steps to improve architecture In Study Sapuri Android
  20. #sapurimeetup LiveData 27 [Before] 一つのError fieldに複数の種類のErrorを非同期で通知 private var _errorDebug: MutableLiveData<Error>

    = MutableLiveData() val errorDebug: LiveData<Error> get() = _errorDebug fun clickDebugButton() = viewModelScope.launch(IO) { _errorDebug.postValue(Error.Hoge) } fun clickDebugButton2() = viewModelScope.launch(IO) { _errorDebug.postValue(Error.Fuga) } ViewModel.kt Baby steps to improve architecture In Study Sapuri Android
  21. #sapurimeetup LiveData 28 期待値は Hoge も Fuga も通知してほしい onCreateView: error

    is observed Hoge onCreateView: error is observed Fuga binding.debugButton.setOnClickListener { viewModel.clickDebugButton() viewModel.clickDebugButton2() } Fragment.kt Logcat Baby steps to improve architecture In Study Sapuri Android
  22. #sapurimeetup LiveData 29 実際は Fuga のみ通知される(場合がある) • ほぼ同時に postValue が呼ばれると値が抜ける

    • delay() などでタイミングをズラすと呼ばれる onCreateView: error is observed Fuga Logcat Baby steps to improve architecture In Study Sapuri Android ※ version 2.1.0-alpha02
  23. #sapurimeetup LiveData 30 [After] Error種類によってLiveDataを分けるように変更 fun clickDebugButton() = viewModelScope.launch(IO) {

    _errorHoge.postValue(true) } fun clickDebugButton2() = viewModelScope.launch(IO) { _errorFuga.postValue(true) } ViewModel.kt Baby steps to improve architecture In Study Sapuri Android
  24. #sapurimeetup コードレビュー 31 • Convert to Kotlinのコードレビューがしにくい ◦ 自動変換のものとマニュアルの変更のコミットを分ける •

    細かいコーディングスタイルは進めながら議論 ◦ どの単位でRepositoryを切るか ◦ nonnullにできるところ/lateinit,lazyが使えるところ ◦ スコープ関数何を使うか Baby steps to improve architecture In Study Sapuri Android
  25. #sapurimeetup タスクのアサインと知見共有 32 • DBのマイグレーションなど複数人作業に効率の悪いタスクは専任を決める ◦ 開発途中でブランチを移動するとBuildに時間がかかる • 勉強会を開き知見を共有 ◦

    e.g) Roomの導入 ◦ e.g) RxJavaのコードで起こしやすい不具合の共有 • 特に複雑度の高い画面はペアプロで進める Baby steps to improve architecture In Study Sapuri Android
  26. #sapurimeetup 取り組みの結果 34 • Phase1: Migrate GreenDao to Room ◦

    完了 • Phase2: 大規模案件に影響する画面のKotlin化、MVVM化 ◦ 完了 • Phase3: その他の画面のKotlin化、MVVM化 ◦ Kotlin化 49% ◦ MVVM化 44% Baby steps to improve architecture In Study Sapuri Android
  27. #sapurimeetup アーキテクチャ改善は必要か? 35 • Yes. • 当時考えられて作られたアーキテクチャでも開発メンバーも変わればアーキ テクチャの良さも変わる ◦ 開発する自分たちに合うものに変える

    ◦ 自分たちが開発していて気持ちいい環境にする • ドメイン知識の伝承 ◦ 知らない仕様で起きる不具合が多かった Baby steps to improve architecture In Study Sapuri Android
  28. #sapurimeetup まとめ • Study Sapuri Androidチームは地道なアーキテクチャ改善を続けてきまし た…!! • リファクタによる恩恵 ◦

    ”複雑な仕様の伝承” ◦ 開発スピード/品質の改善 • 今のアーキテクチャに固執しすぎない、常に良い形を模索していくチーム 39 Baby steps to improve architecture In Study Sapuri Android