コメントは失敗か?
はじめに: コメントは失敗である
実際のコメントは、せいぜい良くて必要悪なのです。
もしプログラミング言語が表現力が十分であれば、あるいは我々に、この言語を巧妙に使って我々の意図をうまく表現する才能があれば、
コメントは、大して、いやおそらくまったく必要ないのです。
適切なコメントの使用方法とは、コードでうまく表現することに失敗したときに、それを補うのに使うことです。。
ここで「失敗」という言葉を使っていることに注意してください。
私は、この言葉を意図して使っています。
コメントは常に失敗なのです。
いつも我々自身の意図をコメントなし表現できるわけではありません。
このため喜ばしいことではありませんが、コメントを使わなければならないのです。
上記は、ロバート・マーティンは著書「Clean Code1」からの引用です。
この言葉は、真実でしょうか?
本当にコメントは、かつては必要であったが、現代では捨て去るべき因習なのでしょうか?
コメントの効用
コメントには様々な効用がありますが、今回注目するのはコメントがコードを抽象化するという点です。
抽象化とは、それ自体抽象的な言葉ですが、ここでは「複雑さを隠蔽し、理解しやすいメンタルモデルや直感的理解を提供すること」とします
コードがうまく書かれていれば、コメントは必要ないほど明白(=抽象化されている)だと考えている人もいます。
この考えは、完全に間違った考えとは言えませんが、同時にプログラミング言語の表現力を過大評価しているとも思います。
プログラミング言語によって提供される抽象化機能である、関数の宣言について考えてみましょう。
fn substring(source string, start int, end int) string
上記のような関数宣言を見た開発者は、より詳細な情報を必要とせずに
「この関数は、文字列を受取、指定された範囲の部分文字列を返す関数なんだろうな」
と理解することができるでしょう。
つまり、関数宣言はコードを抽象化しています。
しかし、この関数を使う上でついて知るべき情報は、これだけでは十分とは言えません。
- start, end の位置の文字は結果に含まれるのか?
- start が負の値の場合、どのような挙動をするのか?
- end が負の値の場合、どのような挙動をするのか?
- end < start の場合、どのような挙動をするのか?
- end が文字列の長さより大きかった場合、どのような挙動をするのか?
- source が空文字あるいはnull出会った場合、どのような挙動をするのか?
などと言った情報が欲しくなるでしょう。
これらの情報を得るための唯一の方法が実装コードを読むだけであったとしたら、この宣言はコードの抽象化に失敗していると言わざるを得ません。
もし、これらに対する情報が関数のヘッダコメントに含まれていたとしたならば、関数を利用としい開発者は実装コードを読む必要がなくなるため、関数の抽象化は守られることになります。
このように、プログラミング言語の表現力には限界があるため、それだけで抽象化を守ることは非常に困難になります。
なぜコメントはこれほど嫌われているのか?
現代におけるコメント恐怖症は、書くべきではないコメントばかり書かれ、真に書かれるべきコメントがないがしろにされ続けた結果と言えます。
では、具体的に書くべきではないコメントとはどのようなものでしょう
コードの内容を繰り返しているだけ
a += 1; // aに1を足す
不要なコメントと言われて真っ先に思い浮かぶのは、このケースでしょう。
また、次のような変数名を繰り返しているコメントも不要です。
// テキストの水平方向のパディング
private static final int textHorizontalPadding = 4;
このようなコメントは、単純に書くのをやめましょう。
プログラミング言語では表現しにくい情報を補完できていない
上記のtextHorizonalPaddingという名前の変数を見たプログラマは
- パディングはテキストの右側につくのか?それとも左側か?両方か?
- パディングの単位はなにか?文字数?それともpx?
- そもそもpaddingとは何を意味しているのか?
などと言った情報も欲しくなるかもしれませんが、それらをプログラミング言語が提供している機能だけで提示するのは簡単ではありません。
変数の意味を表した良い名前をつけることでこの問題に対応できることもありますが、多くの場合ただただ長くて覚えにくい名前になるだけでしょう。
そこで、そのような情報を伝えるためにコメントを使うことにします。
// テキストの各行の左右に残す空白の量(ピクセル単位)。
private static final int textHorizontalPadding = 4;
これだけの単純なコメントでも、多くの情報を伝えることができることがわかると思います。
実情に合わない古いコメントが、後の開発者に誤解を与えることがある
確かに、実装とずれたコメントや意味のなくなったコメントというものはよく見る問題です。
しかし、そういったコメントは多くの場合、コードが何をしているかを繰り返して説明しているだけの書くべきではないコメントであることが多いと思うので
書くべきコメントのみを書くことを心がけていれば避けることができる問題だと思います。
それとは別に、仕様が変更され既存の関数に大きな変更が入った場合などに、コードは変更されるがヘッダコメントはそのままだったりする場合もありますが、
このケースではコメントが更新されていないことが間違いなので、コードレビューで指摘するべきだと思います。
AIによるコードレビューはコードとコメントのズレを検出してくれるので、この問題は今後減っていくのではないかと考えています。
書くべきコメントとはなにか
ソフトウェアを継続的な開発しつづけるには、様々な問題がありますが、よいコメントは以下のような問題に対する処方箋(無論完全なものではありませんが)となります。
- 認知負荷: 変更を行うために、開発者は大量の情報を蓄積しなければなりません
- 未知の未知: どのコードを変更する必要があるのか、またはそれらの変更を行うためにどの情報を考慮しなければならないのかが不明確です
つまり
- 開発者が変更を行うために必要な情報を提供し、無関係な情報を無視しやすくするコメント
- コード上には現れない、コード製作者の意図を表現したコメント
- モジュールを跨いで現れる、把握しにくい依存関係を表現したコメント
といったコメントこそが書かれるべきなのです。
おわりに: コメントは失敗ではない
この文章の内容は、主に「A Philosophy of Software Design2」の内容をもとにしています。
この本は、無駄なコメントが多すぎるという意見には同意できるが、すべてをコードだけで説明できるという意見には同意できないと、
筆者がコメントに対する態度を決めかねていた時に読み、考えをまとめるきっかけとなった本です。
今回はその内のコメントについてだけ書きましたが、プログラミング設計全般について扱った本なので、設計に興味のある方々には、是非読んでいただきたい一冊です。
(日本語訳の予定は見当たりませんが、今ならAIが全部訳してくれたので問題なかったです)
最後に、この文章を読んでコメントの必要性を感じていただけたのでしたら、是非意識して良いコメントを書いていってください。
コメントを書いたからといって、何か批判されるいわれはないのですから。