Refactoring Day：技術的負債をリボ払いする

[株式会社 nana music](https://nana-music.com/)でサーバーサイドエンジニアをしている @_kobacky です。この記事は nana music Advent Calendar 6日目の記事になります。
[またお前かよ](https://qiita.com/_kobacky/items/c4b168001d2eedfbab7f)って感じだとは思いますが、個人的に「カレンダーの空枠をどれだけ埋められるかチャレンジ」を勝手に始めてみました。[^1]

[^1]: Advent Calendar は nana としては今年初めて実施された企画で、とにかく始めたこと自体に意味があると思っているけど、せっかく @xKxAxKx が音頭取って企画してくれたのでなるべく埋めたいというお気持ちがあります。

ということで今日は小ネタを一つ。
nana のサーバーチームでは定期的に KPT でチーム運営を振り返って改善案を考えたりしているのですが、その中で個人的に良かったなと思ってる Refactoring Day について紹介したいと思います。

## 前提： nana の開発
まず前提として nana がどんな開発体制・開発プロセスなのかの概要を説明します。[^2]

[^2]: ただし開発プロセス自体の改善も継続的に続けられているため、あくまで現時点におけるプロセスを切り出した説明になります。

- 開発チームは Product Owner (PO) / Server / Android / iOS / 音声処理 のチームから成ります。
- 開発の長期的なロードマップは PO と他チームのリーダーを中心に決定されます。
- ロードマップで定義された開発項目 (Project) は各チームのメンバーに担当が割り振られます。Project の内容に応じて Project Manager 的な人も決められます。
- 開発自体は2週間のスプリントで行われます。2週間のスプリントの運営は各チームの裁量に任せられています。

## Refactoring Day とは
簡単に言ってしまうとスプリントの初日をみんなでリファクタリング(を中心とした改善活動)する時間に充てようというだけの話です。
この日には各 Project の開発ではなく下記のようなことが行われます。

1. 長年の機能追加で発生した重複コードや設計の崩れてきたコードの改善
2. テストコードの高速化・拡充
3. 運用を楽にするためのツール開発
4. 今後の開発を楽にするようなライブラリ・ツール等の検証
5. リソースの整理 (不要なインスタンスやファイルが残ってたら消すとか)

本来の意味でのリファクタリングとは「1」を指すと思うのですが、そこはあまり厳密には考えず **開発・運用の効率を上げるための活動** といった緩い定義で捉えています。
また、 Refactoring Day に何をやるかは基本的に各メンバーの裁量に任せられています。朝会で「今日はコレをやろうと思います」と宣言して、それに取り組むという感じです。

## 何が良いのか
### 定期的に技術的負債の返済ができる
当たり前の話ですがメインはこれです。
nana のようなスタートアップはサービス的にも長期的な見通しを立てるのが難しい側面もあり、結果的に開発時に考えていた設計と異なる運用になったり、時間的な問題からどうしても場当たり的なコードを書かなければならないこともあります。
施作のための機能追加 Project を優先しすぎると、どうしても設計的に矛盾があったり重複したりするコードが蓄積されてしまいます。これにより例えば下記のような弊害が発生します。

- 開発効率が低下する
- 新規メンバーのキャッチアップコストが大きくなる
- ツラい感じのコードや運用等に出会った時にツラくなる

これらを避けるために定期的に負債は返済していかなければならない・・と言うと当たり前の話なんですが、新機能の開発が詰まっていたりするとどうしても後回しになってしまいがちです。
しかし Refactoring Day を設定してスプリントの中で定期的にやることを決めてしまうだけで、意外とすんなりその時間が取れるようになったなという印象です。

個人的に特に良いなと思っているのは、前のスプリントの開発で出会った負債をすぐに改善することができるということです。(規模にもよりますが。)

開発を進めていると、前提となっている部分のコードで「修正したい！でもここに手を入れると他の機能の部分にも影響してくるから今の開発とは切り分けて修正したい。。」という部分に出会ったりします。
そういった場合でも、翌スプリントの Refactoring Day に修正できることがわかっていれば、一旦その時は既存のコードに合わせて開発を進める判断もしやすいです。
Refactoring Day がなかった時は、その場で解決しようとして本来の機能の開発のリズムが狂ってしまったり、逆に、積み残す判断はしたけど結局解決しないまま忘れてしまうということも発生しやすかったように思います。

### チームメンバーの知識共有・スキルアップに繋がる
nana ではチームメンバーそれぞれが異なる Project の開発をしているので、何も対策しなければメンバー間の知識差が出て来がちです。また、メンバーの経歴も様々でスキル差もあります。[^5]
[^5]: どちらかと言うとスキルの高低というよりはスキルの多様性という意味。
Refactoring Day はこの問題に対して下記の効果をもたらしていると感じます。

- リファクタリングの過程で自分が開発に関わっていない部分のコードにも触れることができてメンバー間の知識共有が進む
- リファクタリングのプルリクエストを見ると他のメンバーが考えた設計に触れる機会が得られ勉強になる

また、次の Refactoring Day に何をリファクタリングしようか考えながら開発する癖ができ、より良い設計を考える習慣が付くのも良いところかなと感じます。

## 進め方のコツ
Refactoring Day でのリファクタリングを実際にやって見て感じたことですが、基本的には1日で終わる単位に分解して進めるのがコツだと思います。これは下記の理由からです。

- 1日で終わらないと2週間空いてしまい思い出すコストがかかる
- リファクタリングは難易度の高低に関わらず修正がソースコードの広範囲に及ぶ可能性があり、長期化するとマージする時にコンフリクトが発生しやすい

基本的に Refactoring Day で実施する改善は小規模なものの方が向いていると思います。1週間ぐらいガッツリ時間のかかるような項目は、スプリントのタスクとして集中して実施した方が良さそうです。

また、比較的気持ちに余裕のあるスプリントの初日に設定するのが継続するコツだと思います。[^7]
[^7]: スプリントの初日はだいたい月曜日だと思いますが、基本的にリファクタリングは楽しいので休み明けの憂鬱が軽減されるというメリットもあります。これは自分だけの話かもしれませんが。

### 終わりに
今回は小ネタとして、nana のサーバーチームで実施している Refactoring Day という取り組みについて紹介させて頂きました。基本的にリファクタリングとは物事を良い方向に改善するための活動ですし、そういった改善活動を継続的に行えていることが精神衛生的な意味でも良いなという気がします。
技術的負債との付き合い方については各社それぞれ工夫して取り組まれていると思います。もちろん Refactoring Day みたいな施作をしなくても継続的に技術的負債の返済ができているチームもあるでしょうし全てのチームにとってフィットするものだとは思いませんが、現在の nana のサーバーチームにとってはフィットする良い案だったのではないかと感じています[^6]。
この記事が一つの事例として何かしらの参考になれば幸いです。

[^6]: ちなみに Refactoring Day はチームリーダーの @rinist が考えてくれたものです。ナイスアイデア！

~~ちなみにまだ明日も枠空いてるので、もしかしたらまた何か書くかもです。~~ -> なんと @akihito-okada が明日書いてくれることになりました！ お楽しみにー。