開発者ならだれもが、自分のコードに最低一行はコメントを書いているはずだ。コメントをたくさん書いて、コードをもっとわかりやすくしようとする人もいる。この記事では、コードにコメントを書くときに使われるプラクティスを集めてみた。
Seattle Area Alt.Net グループのメンバらが、コードにコメントを書く必要性やプラクティスについて議論した。Kelly Leahy氏は、一目瞭然のわずかなコメントが散りばめられているようなコードが好みだ。コメントは「コードを変更したときに取り残されてしまうことが多く」、「不正確なノイズをシステムに取り込んでしまうだけ」だと考えているためだ。
(コメントを書くということは)多くの人にとって個人的なことですが、私はコメントをかなりスリムにするよう気を配っています。というのも、コードを変更したときに、コメントが取り残されてしまうことが多いためです。もはや存在しないコードを参照しているコメント。もはや存在しない挙動を参照しているコメント。(だれかがコメントと元のコードの間に新たにコードを挿入したため)直後にあるコードを参照していないコメント。コードを変更したのにコメントだけがそのまま残されて、もはや正しくないコメント。そういったコメントを私は何度も何度も見てきました。
このようなコメントは、コメントがないこと以上に、まずいことだと思っています。だから、私はコメントを書かないようにしているのです。
Leahy氏はコメントを全く書いていないわけではなく、コード一万行につきコメント一行ほどは書いているそうだ。
少し説明しておく必要がありそうな避けられない設計上の制約(パフォーマンス変更など)がある場合には、コメントが役に立つこともあります。それでも、私はコメントを書かないよう努力します。おそらく、コード一万行につきコメント一行程度でしょう(たわいもないxmldocコメントは除きます。個人的には、公開APIの場合を除いて、役に立たないと思っています)。
Justin Rudd氏は、現在のプロジェクトではAPIがあまりにひどいため、コメントをたくさん書く必要があったと説明した。
ちょうど今、私はVisual Studioのためのソース管理パッケージを書いています。そのAPIはあまりにひどいので、自分が何をしているのかコメントを入れておく必要があります。そうすることで、ある場所ではGuid.Emptyを渡して、(一見すると同じように見えるのだが)別の場所では特別なGUIDを渡さなければいけない理由を思い出すことができます。さもないと、忘れてしまいます。
私は4つのソリューションのイベントインターフェイスのどれを実装しているか、コメントを入れています。そうしておけば、次に参加して7つのメソッドのうち6つを消そうと思った人も、それらを消さないでしょう。
私はそのメソッドが特別なHRESULTを返す理由をコメントに書いています。S_OKを返すと、Visual Studioがクラッシュするためです(Microsoft Connectに書かれています)。
また、たとえドキュメントにnullが渡せると書いてあっても、実際のところできないのであれば、そのことをコメントに書いておきます。
このプロジェクトの場合、おそらくコード2に対してコメント1の割合になっています。
Chris Tavares氏はバグ修正のためにコメントを使っている。
"// doing this because it fixes bug #####(バグ####を修正するため)"というコメントは不吉な臭いのするものではありません。実際のところ、これは必要不可欠なものです。
これに対して、Brandon Molina氏は、バグ修正のためのコメントはコードの内部に入れるのではなく、バージョン管理システムを使うのが望ましいと考えている。
バグが10個あるときには何が起こるでしょう? コードは最新であっても、コードを乱す無意味な情報のかたまりができてしまいます。こういった目的には、バージョン管理システムを使いましょう。コメントとdiffを組み合わせることで、コメントは本当に有益なコンテキストを持つことになります。
Brad Wilson氏は、不吉な臭いのするコメントを避けるための指針となるルールを付け加えた。
「なぜ」というコメント == 役に立つ
「どのように」というコメント == 疑わしい
Timo Hilden氏はコードのコメントについて書いており、役に立つコメントを書く必要性について次のように主張した。
コードにコメントを書くことを軽視するのは簡単なことです。考えてみましょう。私たちはプログラマとして、ピューリッツァー賞を取ることはできないでしょう。したがって、自己表現するための個人の能力が欠けているわけではないのです。はっきり言って、怠けているだけなのです。
正直に言って、必要なところにコードを説明するコメントを何も残しておかないのは、何か残しておくのと比べると、ずっとよくないことです。第一に、そのプログラマは同僚に対して敬意を払っていないことを間接的に示しています。数十のクラスや謎めいた見てもすぐにはわからないコードのある関数といったものを苦労して読むのがどれだけ苦痛なものか、だれもが知っているはずです。元のコードを書いた人が休暇中だったり、すでに会社を去っていたり、何らかの理由でアクセスできないのなら、なおさらです。プログラマというのは、同僚のプログラマを顧客として持つ芸術家です。したがって、あらゆる芸術家と同様に、私たちは顧客に敬意を払うことを学ばなくてはなりません。
第二に、コメントを省略するのは、プログラマの慢心を示しています。実際にコードを書いているときには、やろうとしていることにうまいアイデアを持っているものです。しかし、プログラミングというものは、たいていの場合、頭の中で同時に複数のことを操らなくてはなりません。次回コードを見るときには、元のコードを書いたときと同じ思考に戻すのは、非常に難しいでしょう。こうした状況はよくあるので、適切なところにコメントで説明しておいて損することはありません。
Hilden氏は、何年か前にScott Swigart氏やJeff Atwood氏が言及した「Undocumentation」というプラクティスを支持していないと言う。次のコメントを書きすぎた例について考えてみよう。
// Declare category id for products(製品のカテゴリIDを宣言する) const int prodCategoryId = 1024; // Create an iterator over products(製品のイテレータを作成する) vector<Product>::iterator iter = products_.begin(); // Iterate through all products(すべての製品をイテレートする) for ( ; iter != products_.end(); ++iter ) { // Assign categody id to each product(各製品にカテゴリIDを割り当てる) iter->AssignCategoryId( prodCategoryId ); }
彼はこれらのコメントを、ステップごとでなく一般的な考えを説明したコメントにまとめるよう提案した。
// Assign categody id to each product(各製品にカテゴリIDを割り当てる) const int prodCategoryId = 1024; vector<Product>::iterator iter = products_.begin(); for ( ; iter != products_.end(); ++iter ) { iter->AssignCategoryId( prodCategoryId ); }
あなたはコメントを書くために、どんなプラクティスを使っているだろうか? 会社で強制されているプラクティスや、自ら選んだプラクティスというのはあるだろうか? 「できるだけコメントを書くのを少なくする」というポリシーを支持して、次の開発者があなたのコードを理解してくれると信じているだろうか? あるいは、あまり明確でないものを文書化しておくのに時間をかけるべきだと考えているだろうか?