Slide 1

Slide 1 text

2023/6/15 日本経済新聞社  サブスクリプション事業デジタル編成ユニット 夏坂 友輔 Androidチームにおける レガシーコードとの向き合い方 NIKKEI TECH TALK #8

Slide 2

Slide 2 text

自己紹介 2 ● デジタル編成ユニット アプリチーム ● 夏坂 友輔(なつさか ゆうすけ) ● 2020年10月 中途入社 ● @ntsk ● Androidアプリのレガシーコードの改善に取り組んでいま す

Slide 3

Slide 3 text

本日話すこと 3 日経電子版、日経紙面ビューアーのAndroidアプリはリニューアルのあった、 2015年から8年ほど運用しているコード。 HandlerやAsyncTaskLoaderを駆使した昔ながらの実装から、Coroutines FlowやComposeを利用した最新の実装まで様々。 僕たちのチームのレガシーコードにまつわる課題を紹介しつつ、解決のためのア プローチについて紹介します。

Slide 4

Slide 4 text

レガシーコードとは 4

Slide 5

Slide 5 text

レガシーコードとは 5 t ● テストのないコード、テストができないコード ● 修正や拡張、作業が難しいコード 参考 ・Michael C Feathers.「レガシーコード改善ガイド」 . 2009/7/14. 翔泳社 ・David Scott Bernstein. 「レガシーコードからの脱却」 . 2019/9/19. O’Reilly Japan

Slide 6

Slide 6 text

僕たちのアプリにおけるレガシーコード 6 ● 実装当初からテストがない、もしくはテストしづらい実装のもの ○ 実装初期などテストを書く文化形成以前に実装された ○ AsyncTaskLoaderを利用した非同期処理が残っていたり、UIとロジックが 密結合しておりテストが書きづらい ○ 更新頻度が低いアプリ・画面だと長い間そのままになっている

Slide 7

Slide 7 text

僕たちのアプリにおけるレガシーコード 7 ● Androidアプリ開発のスタンダードが変化することによってレガシーになったもの ○ アプリアーキテクチャガイド登場以前の複数世代のアーキテクチャが混在 ○ 当時はメジャーだった古いサードパーティライブラリと設計が密結合している ○ BaseActivity, BaseFragment, BasePresenter, BaseFragmentViewなど継 承を利用した画面が多く、ライフサイクルのタイミングが異なるケースなど都度継承 元の実装に対する考慮が必要 ○ その他、OSやSDKのバージョンアップに伴って修正が必要なもの

Slide 8

Slide 8 text

僕たちのアプリにおけるレガシーコード 8 ● サービス要件の変化が積み重なってレガシーとなったもの ○ ローカルDBのテーブル設計がドメインモデルの変化とマイグレーションを繰り 返す中で扱いづらくなってきているが、全体を再設計してマイグレーションする コストも高い。OrmLiteやRealmが採用されているが再設計に合わせて Roomに移行もしたい。

Slide 9

Slide 9 text

僕たちのアプリにおけるレガシーコード 9 ● 短期的な不具合修正が積み重なってレガシーとなったもの ○ 障害発生時に暫定対応を行なったコードを追加してリリースし、恒久対応につ いても方針だけは決まっているが実装されていない

Slide 10

Slide 10 text

レガシーコードによる影響 10

Slide 11

Slide 11 text

不確実性の増加 11 レガシーコード比率が高い画面に対して、機能追加に時間がかかる。 ● 主要な画面ほど機能が多く複雑性も高い。歴史も長いのでレガシーコードの比率 も高く単純な機能追加でも時間がかかる ● テストをかける状態にするまでのステップが多い ● 不確実性が高いので単純な機能追加でも見積もりのバッファが大きくなる

Slide 12

Slide 12 text

予期しない不具合の発生 12 レガシーコード起因の不具合がたびたび発生 ● Baseクラスのライフサイクルに起因したクラッシュの発生 ● Chromeのアップデートに伴いWebViewの表示が崩れる ● DBパフォーマンスの劣化 ● ANRの発生

Slide 13

Slide 13 text

レガシーコード改善が永遠に終わらない問題 13

Slide 14

Slide 14 text

レガシーコード改善が永遠に終わらない問題 14 中長期的な開発速度や開発者体験が低下することによるリスクについてはチームは 理解している。 だからこそ新機能開発時の事前リファクタリングや、細かなコード改善を日々行なっ ているが、それでもレガシーコードによる負荷がいつまで経っても減らない。

Slide 15

Slide 15 text

レガシーコード改善が永遠に終わらない理由 15 1. レガシーコードを要因とした中間的実装の増加   Aで実装したいがB(レガシーコード)が要因でCの実装を行う ● Bがアプリケーション全体に影響するなど即時解決困難な課題の場合、機能 開発を優先するためCの実装が増え続け、Aの実装が増えない ● 問題発生時に暫定対応を行い、恒久対応のためのIssueが作られるが、恒久 対応の優先度が上がらない ● 将来はAにしたいけどCになってるという経緯を理解する負荷が増える

Slide 16

Slide 16 text

レガシーコード改善が永遠に終わらない理由 16 2. レガシーコードの解決に必要なタスクが時間と共に肥大化 ● Aの実装にはBの実装にはCの実装にはDの実装には(以下ループ) ● 時が経つにつれ解決に必要な作業が増えていく ● 巨大に膨れ上がり、触ることのできない課題になってしまう ● 触ることができないのでさらに巨大化していく

Slide 17

Slide 17 text

レガシーコード改善が永遠に終わらない理由 17 3. チームメンバーがみんな機能開発をしている ● 機能開発と一緒にリファクタリングする場合、その機能に関わる画面にしか着 手できないので根本解決ができない ● スプリントの範囲内で終わるような課題にしか取り組めない ● 並行して様々な機能開発が進むため認知負荷が高まる

Slide 18

Slide 18 text

レガシーコード改善が永遠に終わらない理由 18 4. 開発案件とコード改善のバランス・優先度設定の負荷が高い ● 機能開発とコード改善は目的とする指標が異なるため、適切な優先度設定が 難しい。チーム外から依頼されたり規模の大きいプロジェクトが走るとそちら に注力しがちに。 ● コストパフォーマンスの高いものから優先的に着手すると、工数が大きいアプ リケーション全体に関わる問題については優先度が上がりづらい

Slide 19

Slide 19 text

19

Slide 20

Slide 20 text

レガシーコード改善を進めるための アプローチ 20

Slide 21

Slide 21 text

継続的にコード改善を行えるチーム体制に 21 これまでの開発体制(~2023/3) ● コードの改善も含め、全てのタスク を1つのバックログで管理し優先度 を設定 ● チームメンバーはバックログの優 先度順にタスクに着手 Conversion Onboarding Retention Product Backlog Sprint Backlog Code Refactoring

Slide 22

Slide 22 text

継続的にコード改善を行えるチーム体制に 22 変更後の開発体制(2023/4~) ● 中長期的な技術的課題のみの優 先度に絞って開発を行うチームを 分割 ● 技術的課題の解決による指標を 設定し改善できるようにする Conversion Onboarding Retention Product Backlog Sprint Backlog Code Refactoring Product Backlog Sprint Backlog

Slide 23

Slide 23 text

継続的にコード改善を行えるチーム体制に 23 新体制のモチベーション ● チームの目的と責任範囲を明確にすることによる認知負荷の低減 ● 安定した改善のための工数が確保 ● アプリケーション全体に関わるような中長期で取り組む必要のある問題につ いても着手できる ● 人数が増えてきたこともあり、チームを今後どのようにスケールさせていくか の実験的な取り組みでもある

Slide 24

Slide 24 text

継続的にコード改善を行えるチーム体制に 24 メトリクス・指標の作成やチームの目標設定 ● 目標の設定によりチームの存在意義が明確に ● 開発チームのパフォーマンスを表す指標としては「Four Keys」が有名だが、デ プロイ頻度などモバイルアプリ開発と完全にマッチしない部分もある ● 開発におけるリードタイムや、アーキテクチャ適応度関数、レガシーコード比率、 変更障害率などのチームの実情にあった可視化を行い改善する

Slide 25

Slide 25 text

継続的にコード改善を行えるチーム体制に 25 認知負荷の種類から適切な境界を模索する ● 課題内在性負荷 ○ 問題領域の本質的なタスクに関連するもの ● 課題外在性負荷 ○ タスクが実施される環境に関連するもの ● 学習関連負荷 ○ 学習を進めたり高性能を実現したりする上で、特別な注意が必要な タスクに関連するもの 参考 ・Skelton Matthew, Pais Manuel 「チームトポロジー」日本能率協会マネジメントセンター

Slide 26

Slide 26 text

継続的にコード改善を行えるチーム体制に 26 まだまだ課題は山積み ● iOS/Android共通の技術課題の解決 ● コード改善に対する適切なKPI・閾値の設定 ● リグレッションテストをはじめとしたQAコスト ● etc… フェーズに合わせて適切にチームやアーキテクチャを進化させていく

Slide 27

Slide 27 text

ありがとうございました! DroidKaigi2023にもadbに関する内容で登壇しますので 是非聞きに来ていただけると嬉しいです! 27