『プログラム書法 第2版』に学ぶコメントの書き方の基礎

ゴールデンウィークなので折角だから借りてきた。

プログラム書法 第2版

プログラム書法 第2版

──というのは嘘。実際の所は、図書館のカードを更新しに行ったついでに気の迷いで借りてしまっただけ。

以前も借りたことがあるのだが、『プログラム書法 第2版』は良い本ではあるけどちょっと古すぎる。サンプルコードがFortran*1PL/I*2である時点でこの本の良さが大幅に削がれている。21世紀のプログラマには色々と厳しい。

まあ今や後継たる『プログラミング作法』がある訳で、普通はそちらを推奨するのだが。

ただ何というか、コメントの書き方に関する記述は『プログラム書法』の方が分かりやすいと思うのだ。分かりやすいというか、『プログラミング作法』よりも基本的な部分に焦点が当てられているというか。単なる気分の問題かもしれないけど。

という訳で、『プログラム書法』に出てくる規則集を元に、コメントの書き方についてまとめてみた。不足する点は他の文献から適度に補うことにする。ちなみに「注釈=コメント」だ。

「注釈とプログラムが一致するように気をつけよう」

コメントとプログラムが一致していないのは、後でソースを読む他人*3をイタズラに惑わすだけだ。ソースコードに手を入れたらコメントも見直すように。

コメントとプログラムが一致しない現象は、次の3パターンに分けられる。

ソースコードは正しく、コメントが間違っている
間違ったコメントの価値はゼロどころかマイナスだ(後でソースを読む人を惑わす点で)。
ソースコードが間違っていて、コメントは正しい
いくらコメントが正しくても、肝心のコードが間違っていたら無意味だ。更に困ったことに、コメントの内容を額面通り信じてしまいソースの間違いに気づかずにスルーしてしまう危険性もある。
ソースコードもコメントも間違っている
もうどうしようもない。

ところでコメントというものは、内容によってはプログラムの中身を二重に表現している場合がある。この場合、プログラムの修正や変更によってソースコードとの食い違いが発生する可能性が高い。

この手の危険性は別の形でコの業界に知れ渡っていると思う。というのも「プログラム設計書(もしくは詳細設計書、etc...)とソースコードが食い違う」という問題と同種である為だ。

要するに同じものを表現した媒体が複数ある場合、どれか1つを修正する際に他の媒体も修正しないと食い違いが発生してしまう為、結局は1度に複数の媒体を修正しなくてはならない。つまりソースコードを修正する際にコメント/プログラム設計書も修正しなくてはならない訳で*4、その分だけメンテのコストがかさむのだ。

ではこの食い違いの発生を避けるにはどうすればよいか? もちろんコメントもこまめにメンテナンスするべきなのだが、メンテのコストを減らすことも重要だ。細かい所で「コメントをむやみにアスタリスク等で囲まない」とか「ソースコードの右側にコメントを付ける際にコメントの開始位置を揃えるように拘りすぎない」などが『Code Complete 第2版』で挙げられている。あまり装飾に注力しすぎると、非本質的な作業に時間がとられてしまうのだ。

さらに大きくメンテのコストを減らす方法は、次項に従うことだ。

「プログラムに書いてあることを注釈でおうむがえしにするのはよそう。つけ甲斐のある注釈をつけよう」

初心者に「コメントを付けましょう」とだけ注意すると発生する、NGパターン。

ソースコードの内容をそのまま自然言語に置き換えたようなコメントは無価値だ。というかソースを読めば済む話なので。そのようなコメントを付ける前に、ソースを適切にインデントするとか、分かりやすい名前を採用するとか、やるべき事が沢山ある。

なによりこの手のコメントは、前項に書いた「プログラムの中身を二重に表現している」にもろに該当している。コード修正の為にコメントもメンテしなくてはならない、厄介な代物だ。無価値なのにコストばかりかかるのだから、当然ながら避けるべきろう。それだけでコメントのメンテナンスのコストが減り、楽になる。

まずはソースコード自体を解説文書となるような読みやすいものにするべきだ。適切なインデント、シンプルな制御構造、分かりやすい名前(変数名、関数名、その他)……これらを採用するだけでも随分見通しのよいソースコードになる。見通しがよければソースの誤りも見つけやすくなるし、ソース本体が読みやすいのだから内容をおうむがえしするコメントなどまったくもって無価値だ。ソースの読み辛さをコメントでフォローしようなど本末転倒だ。

その上で、どのようなコメントを書くべきだろうか? 「つけ甲斐のある注釈」とはどのようなものだろうか?

基本方針として、コメントはソースコード自体からは簡単には分からないような新しい情報を提供するものでなくてはならない。このような内容のコメントはソースコード本体からすると量は少なくなる傾向にあると思う。まさにソースコードが主役で、コメントは添え物程度な訳だ。

私の個人的見解*5としては、HowよりWhat、WhatよりWhyを書くべきだ。

How どのような方法で? 要するにソースの内容をおうむがえししているようなコメント
What 何を? 幾つかの処理をまとめて要約したコメント。基本的にドメインに着目した視点で書く。
Why なぜ? なぜこんな処理をしているのか、なぜこの順番なのか、etc.

Whatはソースコードから分かりにくい or 読み取るのに時間が掛かる場合がある。Whyは大抵ソースコードから読み取るのことが難しい。だからこそ、後でソースコードを読む他人の理解を助けるためにも、Whyは積極的に、Whatは熟慮した上で、コメントとして書き残しておくべきだ。

あとコメントは明快に書くこと。理解を助けるためのコメントがかえって混乱を招いたり、疑問を増やしてしまってはダメだ。

まあしかし、これだけでは実際にどんなコメントを書いたらよいか分かりにくい。とくに経験が浅い人はチンプンカンプンだろう。

「データの割り付けかたについての解説をつけよう」

『プログラム書法』における、つけるべきコメントの内容についての具体的な指針はこれだ。以下、『プログラム書法』より。

プログラムに解説をつけるためにも、もっとも効果的な方法の一つは、単にデータの割り付けかたをくわしく説明する、というものである。おもな変数について、その値としてはどんなものが可能かを示し、それが変って行くようすを説明すれば、それだけでプログラムの解説は、ずいぶん進んだといってよい。

『Cプログラミング診断室』の第3章でも似たようなことが書かれていたりする。

『プログラミング作法』ではより具体的に──関数、グローバル変数、定数定義、構造体・クラスメンバにはコメントを付けるべきだと主張している。関数はともかく、グローバル変数や定数、構造体・クラスメンバはデータやデータ構造に相当する訳で、『プログラム書法』の頃とほぼ同じ主張だと言える。

古来より「アルゴリズムとデータ構造」なんて言われているが、実際にプログラミングで問題を解こうとした場合、まず考えるべきなのはアルゴリズムとデータ構造だ*6。で、データ構造は一旦決まると大きく変化することはないし、プログラム自体もデータ構造に応じて大まかな形が決まってくる。プログラムを何度書き換えようとも、データ構造が変わらない限りプログラム全体の構造も大きく変化することはない。

なんで急にこんな事を書いたかというと、データやデータ構造はプログラミング初心者が考えているよりも重要な要素だと主張したいのだ。重要だからこそ名前(変数名、定数名、構造体/クラス名とそのメンバ名など)に気を遣い、且つ名前だけでは明確にならない部分をコメントしておくべきだ。

「だめなプログラムに注釈をつけるのはよそう。プログラムの方を書き換えよう」

この指針は(仕事でコードを書いているような場合は)常に適用できる訳ではないが、できる限り従うべきだろう。

コードを書いていると、時として複雑で難しい部分が出てくる。そうなると理解の足しとなるようにコメントを付加したくなるのだが、安易にそうする前に一旦ソースコードを読み返すべきだろう。

というのも複雑なコードには次の2種類があるからだ。

  1. そのコードが本質的に複雑な場合。複雑なアルゴリズムを採用しているとか、データ構造が混み入っているなど。
  2. そのコードの出来が悪い場合。そもそもアルゴリズムが良くない、又はデータ構造の選択を間違えているなど。

1番目なら理解の足しとなるコメントを書くべきだが、2番目の場合はソースコード自体を直すべきだ。

1つの判断材料としてコメントの量が挙げられる。基本的にプログラムはソースコードが主役であり、コメントは添え物程度であるはずだ。もしコメントの量が多くなってソースコードが添え物となってしまった場合は、悪いコードを書いていないか注意すべきだろう*7

「注釈をつけすぎないようにしよう」

もしコメントの量が増えてきたら、

  • 不要なコメントを書いていないか?
  • 複雑なコードを書いていないか? その複雑さは本質的なものか?

これらの点を見直すべきだろう。

また事細かにコメントを書いている場合、それが本当に必要なのか見直してみるべきだろう。『プログラミング作法』にも書かれていたが、例えば書籍や論文にでていた何らかのアルゴリズムを用いているような場合、アルゴリズムの中身を事細かにコメントするのではなく、そのアルゴリズムの名称と出典を書くだけで十分だ。

*1:FORTRAN 66ベースらしい。

*2:IBMのチェックアウトコンパイラ3.0準拠らしい。

*3:この他人には「数日後/数週間後/数ヶ月後/数年後の自分」も含まれる。

*4:まあプログラム設計書の類が必要な開発スタイルの場合、本来の筋としては「プログラム設計書を直す --> ソースコードに反映する」という手順で作業しなくてはならないはずだけど……。

*5:……だと思うが、もしかしたらどこかから借りてきた内容かもしれない。うーん、思い出せない。

*6:小規模なアプリケーション、又は大規模プログラムにおけるモジュールやクラスの中身を実装するようなスケールでの話。ちなみに仕様は既に固まっているものとする。

*7:このあたりは苦い経験がある。若手のプログラマにあるソースコード(そのプログラマとは別の人が書いたもの)にコメントを足すように依頼した所、山のようにコメントが足されて返ってきた。その大半が不要なコメントだったので私がコメントを付け直そうとしたのだが、元コードに問題がありすぎてどうにもならず、リファクタリングするハメになった。山ほどのコメントの半分程度は、元コードの筋の悪さを補おうとして付けられたものだったのだ。