miauのブログ

はてなダイアリー「miauの避難所」をはてなブログに移行しました

「いいから黙ってコメント書け」という話

めずらしく釣りっぽいタイトルだけど、ちゃんと主張しておきたいので。

きっかけはこちらの記事。

ここから色々リンクを辿ってみたけど、ほとんどの人が

  • コメントを書かなくてもいいよう、十分明確なコードを書く
  • 関数やメソッド名として切り出せば、その名称で示すことができるからコメントは要らない
  • 処理からでは読み取れない情報(意図)や、複雑な処理のみ例外的にコメントを書く

あたりに結論づけているのにちょっと危機感を覚えました。もちろん「コメントを書かなくても読み取れるようなコードを書く」というのはコーディングする上で大切なことだけど、じゃあ実際にコメントを書かなくてもいいのか、というと別問題でしょう。

私のスタンスは表題のとおり「いいから黙ってコメント書け」というもの。結論としては、

のコメント欄

意図はあくまで意図なので、コードで行われる事実とは無関係に常に書けばいいんですよ。
こういうつもりでコードを書いた、ということを淡々と書く。

と同じことだと思うんだけど、もうちょっと掘り下げて書いてみます。長文注意。

私の意見

まず、本とかに感化される前の私の意見を書いておきます。

こちらの主張である「コメントには処理でなく意図を書く」というのが前提です。

処理から意図を完全に汲むのは難しい

「明瞭なコードを書けば、意図を伝えることができる」という意見がありますが、そんなわけはありません。あくまでも「意図を推測しやすくなる」にすぎないわけです。意図を確実に伝えるためには、コメントを書くのが一番理に適っています。

コミュニケーションの問題であれば「『言わなくても伝わる』という考え方は危険だから、確実に伝えるようにしましょう」みたいなことがよく言われるのに、コメントだとなぜか「書かなくても伝わる」という話になるので、ちょっと不思議です。

コメントが書かれていたほうが速く読める

仮に「読むと意図が十分に伝わる」コードが書けたとしても、コメントがあるコードと無いコードでは、コメントがあるコードのほうが速く読めるはずです。これはコードリーディングのスキルによらず言えることだと思います。コードの処理に対するコメントをいちいち書いていたら読みづらそうですが、上述のとおり処理でなく意図を書いた場合に邪魔になるケースは少ないでしょう。

近年ではオープンソースのプロジェクトも増えてきていて、他人のソースコードを大量に読む機会が増えています。もともと「書くのは一回きりだけど、読むのは何十/何百回かもしれないから読みやすいように書きましょう」という考え方はありますが、より読みやすさに重点を置いてもいいんじゃないでしょうか。

読み手が自分のレベルと同じとは限らない

書き手にとって自明なイディオムでも、それよりも経験が浅い人には意図がつかみにくい処理かもしれません。自分を基準にしてもいいですが、せめて自分よりも 2〜3 段階レベルが低い人にも伝わるように処理を書くべきです。(そうしないと、いつまでもそのコードの保守を引き受ける必要が出てきて困ったりもします・・・。)

関数名やメソッド名は情報量が少ない

ここまでで「説明が必要なだけなら、コメントじゃなくて関数名やメソッド名で示してもいいんじゃないか」と思われるかもしれませんが、それでは不十分です。

というのも、関数名やメソッド名で使える単語はせいぜい 3〜4 語程度です。関数名/メソッド名を簡潔に保ったまま、コメントと同等の情報を含ませることはできません。

「そういう詳しい情報はメソッドコメントに書けばいいんだよ!」という意見もありそうですが、たとえば Eclipse でフロートしたりタグジャンプするのはそれなりに手間です。ここは IDE の進化で解決できるかもしれませんが、現状ではコメントに書いてしまうのがベストと言わざるを得ません。

過度に構造化されたコードは読みにくい

関数化やメソッド化が不適切なもうひとつの理由です。もし一つの関数/メソッドが 40 行の程度になってしまった場合、これを「長すぎるから」と無理やり 10 行のメソッド 4 つに分割すると、分割する前よりも読みづらくなるケースが多いです。(関数名やメソッド名も苦しいものになりがちです。)

もちろん

  • ネストが深くならない
  • 変数名等が適切につけられる

というような理由で読みやすくなるケースもありますし、

  • インターフェイスが明確になる
  • unit test しやすい
  • サブクラスで一部の処理のみオーバーライドしやすい

というような利点もあるため、総合的に見ると関数/メソッド分割する利点のほうが多いかもしれません。でも単純に「読みやすさ」だけを考えるなら、分割せずに適切なコメントをかいておいたほうが読みやすいケースが多いのです。

「関数が長くなると読みづらいから」と読み手に配慮した分割ならまだしも、「コメントを書いたら負け」というような書き手の自己満足のための分割されたコードは、読みづらくなって当然でしょう。(私が入社 2〜3 年目に書いたコードがこんなだったりします・・・。「一画面におさまらない関数を書いたら負け」とか考えて、ひどいコードを書いてました。)

言語の発達でコメントが不要になったりはしない

codeそのものが饒舌になった今、それこそコメントは「蛇足」というものだろう。

のような意見もありますが、言語の発達で不要になるコメントというのは、処理に対するコメントですよね。

現在のプログラミング言語は、コメント以外で意図を正確に伝えるいい手立てはないと思っています。百年後の言語 でできるようになってるといいなとは思いますけど。

この記事については他にも言いたいことがあるので、後でまた言及します。

コードとコメントの不整合はそれほど発生しない

コメントを書く欠点として「コードを保守していくうちにコメントの修正忘れが発生して、コードとコメントが乖離していく」という意見がよく聞かれますが、本当にそうでしょうか。

「コードを変更したい」というのは

  1. 実装を変更したい場合
  2. 処理自体を変更したい場合

の 2 ケースに分かれますので、それぞれについて考えてみます。

まず実装を変更したい場合ですが、コメントの内容が意図だけであれば、これは修正不要なはずです。「コードを修正した場合はコメントも修正しないといけないから手間が増える」とも言われますが、意図を書いておけばそれがリファクタリングの指針にもなりますし、むしろ修正が容易になると私は考えています。

一方、処理自体が変わった場合はコメントとコードを両方とも修正することになります。ここで「コードだけ修正してコメントを修正しない」危険もありますが、常にコメントを書く習慣があれば、ずいぶん発生は減らせるはずです。(私はあまり出会ったことがないです。ただの経験不足かもしれませんが。)

もしコードとコメントの乖離を発見しても、最近であればバージョン管理システムの利用が一般的でしょうから、過去のバージョンを追っていけば乖離のポイントを調べることもできます。必要以上に惑わされることもないでしょう。

習慣としてどちらがいいか

コメントとコードが重複しても実害はあまりありませんが、コメントがなくて実装者の意図が拾えないのはすごく困ります。フェールセーフ的な考えでどちらに寄せるべきかといえば、確実に「コメント推奨」側でしょう。

また、最近は不要論が幅をきかせているせいか、コメント少なすぎます。たぶん以前はよくないコメントをてんこ盛りにする人が多かったから「不要なコメントは書くな!」という論調もあったのでしょうが、残念ながらそんなコメントばかり書く人に出会ったことがありません。今は「コメント書け!」と言っておいたほうが良いと思いますよ。

データの表現について(蛇足)

上記の理由で、コメントが書けない記法(CSV 等)よりも、データのそばにコメントを書ける記法(YAML なり実行コードなり)のほうが私は好きです。テストデータって特に意図が残りにくい部分ですから、コメントはきっちり残したい。

名著をあたってみる(1) - CODE COMPLETE

「そういえば CODE COMPLETE はどうだったかなー?」と調べてみると、第 32 章「読めばわかるコード」がほぼまるまるコメントに関する章になっていました。面白かったのでいくつか引用しておきます。

CODE COMPLETE 第2版 下 完全なプログラミングを目指して

CODE COMPLETE 第2版 下 完全なプログラミングを目指して

すばらしい一言

「32.3 コメントを入れるか入れないか」という項目に劇があるんですが、登場人物の一人であるイスメネ(大きな期待に疲れ、うまくいくプラクティスを探し求めているシニアプログラマ)の台詞にこんなのがあります。

「コメントを書くのを嫌がる人は、(1) 自分のコードが実際よりずっと明確だと思っているか、(2) 他のプログラマは自分のコードにしか関心がないと勝手に思っているか、(3) 他のプログラマを実際より賢いと思っているか、(4) 怠けているか、(5) 他のだれかにコードのしくみを解明されちゃうんじゃないかって心配しているかのどれかね」

私が言いたかったことが一言に集約されていて、ちょっと驚きました。やっぱり CODE COMPLETE すばらしいです。

この本を妄信する気はないけど、たまに指針に迷ったときに読んで、自分の考えと同じだったりすると嬉しい。本当はちゃんと一通り読んでおいたほうがいいんでしょうね・・・。

コメントの種類について

上のほうに書いた私の意見では、結局「コメントには意図を書く」前提に立っていますが、「32.4.1 コメントの種類」でコメントが 6 つに分類されています。

  1. コードの繰り返し
    • 処理についてそのまま書いたもの。
  2. コードの説明
    • 複雑/トリッキーなコードの解説。コードを改良しましょうとのこと。
  3. コードの目印(マーカー)
    • 「TODO」「FIXME」のようなメモ。
  4. コードの概要
    • 数行のコードの概要をまとめたもの。
  5. コードの意図の説明
    • 解決策レベルでなく、問題のレベルを対象としたコメント。
  6. コード自体では表せない情報
    • 著作権表示、コードの設計上の注意点、リファレンスの参照先などなど

このうち「1. コードの繰り返し」は避けるべきコメント、「2. コードの説明」は極力減らすべきコメント、それ以外は削る必要のないコメント、といったところですかね。「3. コードの目印(マーカー)」と「6. コード自体では表せない情報」は・・・確かにそういうのもありますけど、ここでは議論の対象外でいいかなと。

概要コメント

今まではこの中で「5. コードの意図の説明」だけを書きましょう、という主張をしてきたけれど、「4. コードの概要」というのが入っているのがポイントかなと。

そう、意図以外に概要も書いていいんですよね。「処理については書かない」と言いつつ「でも処理の塊ごとにコメント入れることもあるよなー。これは意図と違うよなー。」と微妙に気持ち悪い思いをしていたんですが、これですっきりしました。

これも劇中から引用しておきます。

「コメントを読むとしたら、本の見出しとか目次を読んでいる感じになるといいわね。まず、コメントを読んで正しい部分に目星をつけてから、コードを読み始めるの。プログラミング言語で書かれたコードを 20 行も解析するより、言葉の文章を読むほうがよっぽど速く済むもの」

ほとんどのプログラミング言語は英語をベースにしており、ネイティブな彼らのほうがより違和感なく読めることが想像されますが、それでもコメントを読むほうが速いと言っています。普段日本語を使っている私たちであればなおさらでしょう。

その他指針

コードレビューしたときに「このコード何しようとしてるの?」と聞かれたら、それはコメントが足りないということらしいです。そうしていくうちに、コメントを書く習慣がついていくんだとか。

あと 10 ステートメントにつき 1 つのコメントをつけると、プログラムが最も明瞭になるのだそうです。(引用元は Software Assessments, Benchmarks, and Best Practices という本。)それより高くても低くても、コードの理解しやすさは減少すると。

私の感覚だともう少し多めがいいと思うけど、それは英語と日本語の違いだったり、業務用語への置き換えが必要だったり、そういうことも少しはあるのかなと。

名著をあたってみる(2) - Perlベストプラクティス

さて、一言いわずにはいられない dankogai さんの記事。気になったので Perlベストプラクティスを引っ張り出して読みなおしましたよ。

Perlベストプラクティス

Perlベストプラクティス

コメントの読み手は誰か

以下は「7.11 防御的なドキュメント」からの引用らしいけど・・・

Comment that has puzzled you or tricked you.
あなたが迷ったり勘違いしたところをコメントせよ


ここで注意して欲しいのは、主語が「あなた」になっていることだ。「読者が迷ったり勘違いしたりしそうな」ではないのだ。そう。コメントはあくまでも自分、少し広げてもXPのパートナー用にとどめるべきで、一般読者には取説を用意するべきなのだ。

いやいやいや。you にそこまで強い意味は持たせてないでしょうこの文章は。邦訳書での訳はこう。

迷ったものや頭を悩ませたもにはコメントを付ける

ちょっと自分の好きなように捻じ曲げて解釈しすぎです。そういう解釈が許されるなら you を複数系とみなして「あなたがた」と訳してもいいかもしれない。

そもそもこの章は「コメントをつけましょう」という主張がされている章で、その後にはこういう記述があります。

コメントを明示的に追加すれば、誰がコードを引き継ぐことになっても、同じ誤解を繰り返さずに済む。

コメントを書くかどうかの判断はコードの書き手やその周辺が基準ではなく、読者が基準であるとの主張は明らかです。

コメントを書くべきか

先の記事には、

注目すべきは、Perl Communityは取扱説明書の添付は強く求めても、コメントの書き方に関しては何も言っていない事だ。これはやんわりと「不要」と言っているに等しい。

こんなことも書かれていて・・・・ちょっと待てと。

Perl Community の話は知らないけど、Perlベストプラクティスでは「2.13 チャンク化」「7.9 アルゴリズムのドキュメント」で、CODE COMPLETE でいうところの概要コメントが推奨されています。

このコメントでは、コードによって実装されるプロセス全体に対して、その段落がどのように貢献するのかをかいつまんで説明する。理想的には、すべての段落コメントをつなぎ合わせると、コードがタスクを実行するためのアルゴリズムの要約が得られるようにする。

といった具合。

私も Perlベストプラクティスの全ての記述が正しいとは思わない(不満点は このあたり に書いた)けど、少なくとも作者の意図はそこにない。この本を引用して「コメントは書かないほうがいい」なんて言うのは、さすがにひどすぎです。

コメントの割合について

「7.9 アルゴリズムのドキュメント」で示されているコード例は全体 25 行で、その内訳はコードが 14 行、コメントが 5 行、空行が 6 行。コメント書うんた のデフォルト設定では「コメント率 = コメント行数 / 全体行数」なので、コメント率は 20% と計算されます。紙面の都合でコード行数が増えてるし、実際にはメソッドコメントも書くことになるでしょうから、実際にソースを書いた場合のコメント率はこれ以上になるでしょう。

ステートメント数でいうと、9 ステートメントに 5 個のコメントが付けられている形。Perl は一行にコードが凝縮できますが、だからといって処理の概要が変わるわけではないので、結果としてコメント率は上がるということですね。「高度な言語にはコメントが要らない」の逆を行ってますが、これも私の感覚には合っています。

その他いろんなブログの感想

いくつか印象に残ったものを引用しておきますね。

どういうコメントがいいか?という話

私にとって発端になったこの記事ですが、いい具体例が書いています。

当然、全部が全部コメントなしではなく、こういうところは「なぜこう書いたか?」をコメントに残す。
* わかりづらいところ
* 意図して冗長にしてるところ
* 意図して省略してるところ

後者の二つはかなりポイント高いコメントですよね。見かけたら心の中で「ありがとう!」って叫んでます。

わかりにくいコードを読んだらコメントを書くべし、という主張

最初のほうに挙げた

の後続エントリ。おもしろい考察ですが、気に入ったのはこの一節。

読み取った意図をコメントに残せばいいじゃないか。DRY原則に則って解析処理は1回だけにしておこうぜ。

私もどうしようもないコードに出会ったら、まずコメントを埋め込むところから着手しています。そうでないと、リファクタリングしたとしても、その変更が正しいか他人も判断できませんからね。

Perlベストプラクティス「7.11 防御的なドキュメント」で本来主張されていたのも、こういうことです。

「コメントがなくても分かるコードを書く」のであって「コメントを書かない」わけではない

タイトルが「省コメントのススメ」なので「コメントを書かない」スタンスなのですが、必要なコメントと不要なコメントの解説がわかりやすいのと、

重要なのは、極力コメントを書かないという点ではなく、コメント付与の前に、コード側に問題がないかを考えることなのです。コメントを付与することは、情報をコードとコメントの二箇所に分散させることになるため、一貫性を保つ必要性が出てしまうということを忘れてはいけません。

というような適切な注意書きがあるので気に入りました。

      • -

ふう。長くなったけど、書きたいこと全部書けてすっきり。