増えすぎたTODOコメントは撲滅しなければならない

この記事は[Classi Advent Calendar 2019](https://qiita.com/advent-calendar/2019/classi) 12日目の記事になります。
Classiでバックエンドなどをやっています、@Seigaと申します。アドベントカレンダーに参加するのは初めてなのですがどうぞよろしくお願いいたします。

弊社には[整地部](https://www.wantedly.com/companies/classi/post_articles/145844)という有志による活動があり、モブプロ形式でリファクタリングやパフォーマンス改善などをやっています。ちなみに整地部と名乗り始めた**元祖**らしい。

その整地部活動の1つとしてやっているのが**TODOコメント撲滅運動**です。
この記事ではなぜ撲滅していくのか、どうやって撲滅していくのかといったことについて解説していきます。

## なぜTODOコメントを撲滅するのか

### TODOコメントの漬物化現象 

![image (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75471/280e76f3-6d75-13b4-6b45-bd28695f27c6.png)
*燦然と輝くTODO「実装」コメント(3年もの)*


そもそもTODOコメントとはどういうものでしょうか？
**だいたい上記のようなものです**。
まあここまで酷くなくても、

```ruby
# TODO: メソッド名を適切なものに変更する
```
とか

```javascript
// TODO: モジュール化する
```
のようなTODOコメントを見かけた(or作った)ことはあると思います。TODOコメント文自体の出来不出来はこの際問題ではありません。問題なのは**それらのTODOコメントは役割を全うし、すぐに解消されているかどうか**です。

私たちは[整地部の合宿](https://www.wantedly.com/companies/classi/post_articles/189010)にて4つのリポジトリで合計370個のTODOコメントを見つけ、そのほどんどが1年以上前のものでした。TODOとされたあと、誰にも触られず、忘れ去られ...

`コードは漬物TODOコメントの墓場と化していました`

上記画像もその1つで実際にあったTODOコメントです。ｶﾅｼｲ...ｶﾅｼｲ...。
ある調査では、GitHubの全.NET系リポジトリを対象にTODOコメントがどれくらい放置されてしまうのかを集計した所、**現在あるTODOコメントの62.3％は1年以上前のもの**らしいです。[^the-lifetime-of-todo-comments]

なぜ、TODOコメントは放置されがちになってしまうのでしょうか？
その理解にはTODOリストの問題点を知るのが近道でしょう。

### TODOリストの5つの問題点

[To-Do Lists Don’t Work](https://hbr.org/2012/01/to-do-lists-dont-work)というハーバードビジネスレビューの記事があるのですが、その中ではTODOリストがなぜ機能不全に陥るのかを以下の5つの問題点から述べています。

1. 選択のパラドックス
人は**多すぎる選択肢から1つを選ぶことに大きな負担を感じる**という研究結果がある。
58個のTODOがある時、それらを1つ1つ消化するよりも、1時間メールをチェックすることを選択する。

2. 不均一の複雑さ
リストに3分の長さのタスクと33分の長さのタスクが含まれている場合、タスクを完了した時に生じる心理的な見返りとドーパミン放出のために、**常に短いタスクに集中してしまう**。

3. 不均一の優先順位
TODOリスト内で暗黙的に優先度づけをし、優先度の低いものは最優先に昇格するまで放置されてしまう。明確なメカニズムに基づいた優先度づけではないので、**実は非常に重要なTODOであったとしても判別できない**。

4. コンテキストの欠如
TODOリストは、**作業内容を決定するのに役立つタスクのコンテキストを提供しない**。
なぜやるのか、どのようにやればいいのか、何をもって完了とすべきなのか。この問題はTODOリスト作成からしばらく時間が立った後に再び着手しようとした際に顕著になる。このタスクを完了させるためのコンテキストをまるっきり忘れているのだから！

5. コミットメントデバイスの欠如
最も重要な(大抵最も難しい)タスクに**強制的に着手させるような力学**が欠如しているので、楽なタスクを選択することを防げない。いわゆる背水の陣システム。

要するにTODOリストそのものが、TODOの完了自体にはにまるで無頓着ということが問題視されていました。[^todolist]
同じことがTODOコメントにも言えるのではないでしょうか？

### TODOコメントそのものはTODOコメントの完了にまるで無頓着

TODOコメントが提供する情報は、対応するコードの開始行と、このTODOコメントを残した人が、その瞬間こうすべきだと思ったという思考の残滓だけ...。
強制力もなく、どういう優先度で、どのように、どうして、誰が、いつまでにやるのか、といった**様々な必要情報と紐づいていない**状態です。故に自然と放置されるTODOが増え、いつの間にか漬物TODOの墓場と化すのです。
TODOコメントは技術的負債を示すマーカーです。解消のために力を尽くさないとアプリケーションの負債が溜まっていってしまいます。

よって思ったわけです。

**増えすぎたTODOコメントは撲滅しなければならない**

と...。

## どうやってTODOコメントを撲滅するのか

そもそもTODOコメントの存在意義とは何でしょう？
Uncle BobのClean CodeにはTODOコメントについて以下のように述べています。
>TODOとは、プログラマーがやるべきだと思う仕事ですが何らかの理由で現時点ではできないものです。廃止された機能を削除することを思い出させるか、誰かが問題を見るように懇願するかもしれません。他の誰かがより良い名前を考えたり、計画されたイベントに依存する変更を行うように思い出させるためのリクエストかもしれません。それらのTODOが何であれ、システムに悪いコードを残すことの言い訳にはなりませんが。[^cleancode-quote]

まとめるとTODOコメントの使い道として次のようなものがあります

- 作業リソース的に後回しにせざるを得ないタスク
- 何らかの変更に付随して対応してほしいタスク
- 未来の自分や他の誰かに、より良いコードにしてもらうのを期待する目印

ではこれらの要件はTODOコメントでなければ満たせないものでしょうか？
いいえ、現代では様々なツールや手法の登場により、**TODOコメントに頼らずに要件を満たすことが可能になっています**。以下にいくつか方法を紹介します。

### TODOコメントは適切なトラッキングツールに移行
既存のTODOコメントは削除してしまい、GitHub IssueやAsana、JIRAなど**適切なタスクトラッキングツール**に移行してしまいましょう。ただのTODOコメントよりもずっと多機能で、解決にフォーカスしています。新しく書きたくなった場合もそっちです。

こうすることでトラッキングツール上でのコメントなどを通し適切なディスカッションをすることができます。検討の結果、優先度や担当者、期限の決定ができるはずです。また、詳細なコンテキストの共有をすることで、なぜやるのか、どのようにやればいいのか、何をもって完了とすべきなのか、といった**TODOコメントだけでは分かり得ないコンテキストの明確化**をすることができます。


![スクリーンショット 2019-12-11 22.05.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75471/2c3224cc-3f51-e60f-f250-420b4ff7c95d.png)

*GitHub IssueにTODOタグをつけて書いた例*

この際に3年前など古いTODOで、コンテキストが失われていたり意図がわからないものについては、時間をかけて考古学するより消してしまった方が良い場合の方が多いです。必要になれば要件として勝手に再浮上してくれます。

### TODOコメントをmasterにマージさせない
TODOコメントを書くのは手軽です。なので個人の作業用ブランチ上ではいくらでもTODOコメントを書き込んでしまっても良いと思います。それらTODOコメントは新鮮なので、コンテキストも自分の中にあり、その場で解決する分には難しくないはずです。

ただし、masterにマージされる前に絶対にTODOコメントを解決する**強い仕組み**が必要です。例えば、GitHubアプリの[Check TODO](https://github.com/marketplace/check-todo)はプルリクコードにTODOコメントが含まれている場合GitHub Checksを落としてくれます。

![スクリーンショット 2019-12-11 21.18.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/75471/a683bc5d-3066-4554-b7e9-2f2bd22cad61.png)
*TODOコメントを削除するとCheckが通るようになる*

このようにして強制的にTODOを解消させる(またはIssueなどに移行させる)仕組みを用意することができます。

### 変更を検知することでTODOを腐らせない
変更を検知して強制的にTODOを解決させる、という手法もあります。
次のようなTODOコメントを書きたくなったとしましょう。

```ruby
# TODO: Railsのバージョンが6.0以上になったら本体のBulk insertに置き換える
```

このように「タスクを後回しにするタイプのTODO」ではなく「何らかの変更に付随して対応してほしいタイプのTODO」は工夫が必要になります。
すぐ解決できるタイプではないので、トラッキングツールに置いても放置されがちなタスクとなってしまい、結果的に見逃される可能性があるからです。
どのようにすれば良いでしょうか？

この場合、テストコード中に変更を検知してエラーをRaiseするコードを書きましょう。対応するトラッキングツールへのリンクも添えます。

```ruby
if Gem::Version.new(Rails.version) >= Gem::Version.new(6)
  raise 'Railsのバージョンが6.0以上になったら本体のBulk insertに置き換える'\
        'Issue: https://~'
end
```
このように**変化の検知**さえ仕込めれば、見逃されることなく適切なタイミングでTODOの解消ができます。

## まとめ

かつてGitHub IssueやAsanaもなかった古の時代。コード上の課題を共有する方法として、コード上に直接タスクを書いて共有する手法が流行るのはごく自然な流れでした。課題の場所が分かりやすいですし、何より簡単です。

しかし現在では様々なツールの登場により、そうした要件をTODOコメントを使わずに満たすのはずっと簡単になりました。それらに頼っていけば、きっと撲滅できるはずです。弊社整地部の撲滅活動もまだ道半ば。眠っているTODOコメントはまだまだ多いので、強い意志でやっていきたいものです。

**良い撲滅ライフを！**

次回は@shio312さんです。

## 参考文献
http://wiki.c2.com/?TodoComments
https://dev.to/razbakov/todo-in-code-b
https://dev.to/forstmeier/stop-committing-todos
https://softwareengineering.stackexchange.com/questions/125320/do-todo-comments-make-sense

[^the-lifetime-of-todo-comments]: https://dev.to/petermorlion/the-lifetime-of-todo-comments-the-results-503o
[^cleancode-quote]: 「Clean Code-A Handbook of Agile Software Craftsmanship」 P65 4章 Commentsより翻訳

[^todolist]: 最終的にこの記事ではTODOに入れるのをやめてGoogleカレンダーなどに登録していくことを勧めていました。まあ7年前の記事なので、[Todoist](https://todoist.com)など便利なTODOトラッカーツールを上手く使えば上記の問題点はいい感じに解決できると思います。

[^bots]: 他にも[todoボット](https://todo.jasonet.co/)はプルリク内にTODOコメントが含まれている場合コメントで知らせてくれ、そのままマージするとIssueを自動で立ててくれます。

[^annotation-comment]: 言語に用意されたコメント構文にタグ(トークンとも呼ばれる)をつけて、コードの課題を発見しやすくする非公式な開発文化の1つです。タグとしては他にも`BUG`や`FIXME`、`XXX`などがあります。