ブログトップ 記事一覧 ログイン 無料ブログ開設

Strategic Choice

2014-08-28

[]コメント:情報密度の濃さ:簡潔にする

どういうこと?

コメントは簡潔にします。

どうして?

コメントは画面の領域を取るし、読むのにも時間がかかるので、簡潔なものでなければいけません。

どうすれば?

コメントを簡潔にして、時間と空間を節約します。

例えば、以下は、型定義につけたコメントです。

// int はCategoryType。
// pair の最初のfloat は'score'。
// 2 つめは'weight'。
typedef hash_map<int, pair<float, float> > ScoreMap;

これなら1 行で説明できます。

// CategoryType -> (score, weight)
typedef hash_map<int, pair<float, float> > ScoreMap;

2014-08-27

[]コメント:ライターズブロックを乗り越える

どういうこと?

「コメントを書く」ことに対するメンタルブロックを乗り越えるためには、とにかく書き始めることです。

どうして?

プログラマの多くはコメントを書きたがりません。コメントをうまく書くのは大変だと思っているからです。このような「ライターズブロック」を乗り越えるには、とにかく書き始めるしかありません。

うまくかけなくても、シンプルでも、「何もないよりはマシ」だからです。

例えば、ある関数を作っていて、「ヤバい。これはリストに重複があったら面倒なことになる」と思ったとします。まずは、それをそのまま書き出します。

// ヤバい。これはリストに重複があったら面倒なことになる。

簡単ですし、何もないよりはマシです。ちょっと表現があいまいですが、少しずつ直せばいいだけです。言い回しをもっと詳細な言葉にしてみます。

  • 「ヤバい」は「注意:これには気を付けて」という意味だ。
  • 「これ」は「入力を処理するコード」という意味だ。
  • 「面倒なことになる」は「実装が難しくなる」という意味だ。

書き換えたコメントは以下のようになります。

// 注意:このコードはリストの重複を処理できません(実装が難しいので)。

どうすれば?

自分の考えていることをとりあえず書き出してみます。生煮えであっても構いません。

コメントを書く作業は、3 つの簡単な手順に分解できます。

  1. 頭のなかにあるコメントをとにかく書き出す。
  2. コメントを読んで(どちらかと言えば)改善が必要なものを見つける。
  3. 改善する。

コメントを書く習慣ができれば、「頭のなかにあるコメントをとにかく書き出す」の品質が次第によくなります。最終的には、修正の必要がなくなります。それに、都度コメントを書いていけば、最後にまとめて大量のコメントを書くような事態に陥ることはありません。

2014-08-26

[]コメント:読み手の立場で考える:コードの要約

どういうこと?

関数内部のレベルでも「全体像」についてコメントします。つまり、低レベルのコードに、「要約コメント」を書くようにします。

どうして?

低レベルのコードに「要約コメント」があると、読み手が細部にとらわれずに済むようになります。

以下は、低レベルのコードをうまく要約したコメントの例です。

# 顧客が自分で購入した商品を検索する
for customer_id in all_customers:
	for sale in all_sales[customer_id].sales:
		if sale.recipient == customer_id:
			...

「all_customers」をイテレートしているのはわかっていても、「何のため?」を見失うことがあります。コメントがなかったら、コードを読んでいる途中で意味がわからなくなります。

どうすれば?

コードブロックに「要約コメント」をつけて概要をまとめます。

要約コメントは、関数の内部にある大きな「塊」につけても役に立ちます。

def GenerateUserReport():
# このユーザのロックを獲得する
...
# ユーザの情報をDB から読み込む
...
# 情報をファイルに書き出す
...
# このユーザのロックを解放する

関数の処理を箇条書きでまとめたものなので、詳細を調べなくても、関数の概要が把握できるようになっています*1

関連

「リーダブルコード」筆者は、「WHAT・WHY・HOWをコメントに書くべきか?」について、以下のように述べています。

「コメントにはWHATではなく(あるいはHOWではなく)WHYを書こう」

というアドバイスを耳にしたことがあるかもしれない。確かにキャッチーな言葉だけど、少し単純化しすぎていて、人によって受け取り方が違うかもしれない。

ぼくたちからのアドバイスはこうだ。

「コードを理解するのに役立つものなら何でもいいから書こう」

これなら、WHATでもHOWでもWHYでも(あるいは3つ全部でも)書ける。

*1:ただし、塊を関数に分割できるならそうします。ひどいコードに優れたコメントをつけるよりも、優れたコードのほうがいいからです。

2014-08-25

[]コメント:読み手の立場で考える:全体像

どういうこと?

「全体像」の情報は、コメントに書いておきます。「全体像」とは、以下のようなことを指しています。

  • クラスはどのように連携しているのか?
  • データはどのようにシステムを流れているのか?
  • エントリーポイントはどこにあるのか?

どうして?

新しいチームメンバにとって、最も難しいのは「全体像」の理解です。それは、ソースコードを読んだだけでは得られない情報が含まれているからです。

たとえば、新しくチームに参加した人がいるとします。彼女にはコードに慣れてもらわなければいけません。彼女にコードのことを教える時、ファイルやクラスを指して、こんなことを言うかもしれません。

  • 「これはビジネスロジックとデータベースをつなぐグルーコードです。アプリケーションから直接使ってはいけません。」
  • 「このクラスは複雑に見えますけど、単なるキャッシュです。システムのことは関知していません。」

簡単な会話ですが、ソースコードを読んだだけでは得られない情報が手に入ったことになります。これは高レベルのコメントに書くべき情報です。

どうすれば?

ファイルやクラスには「全体像」のコメントを書くようにします。

システムを設計した人は、こうしたことについて、コメントを書かない傾向があります。あまりにも密接にシステムに関わりすぎているためです。

しかし、なにも「大量の正式文書を書け」と言ってるわけではありません。短い文章で構いません。それでも、何もないよりは、かなり「マシ」なのです。

例えば、以下のようなファイル・コメントです。

// このファイルには、ファイルシステムに関する便利なインタフェースを提供するヘルパー関数が含まれています。
// ファイルのパーミッションなどを扱います。

2014-08-22

[]コメント:読み手の立場で考える:ハマりそうな罠

どういうこと?

コードを使うときに直面する問題を、「前もって」予測できるようなコメントを残します。

どうして?

実行に時間がかかったり、実行すると環境によってハングアップの可能性がある場合、事前にそれを通知することで、トラブルを未然に防ぐようにします。

どうすれば?

読み手が驚くような動作はコメントで文書化しておきます。

関数やクラスを文書化するときには、「このコードを見てビックリすることは何だろう?」「どんなふうに間違えて使う可能性があるだろう?」と自分に問いかけます。

例えば、ユーザにメールを送信するコードを書いたとします。

void SendEmail(string to, string subject, string body);

この関数の実装では、外部のメールサービスに接続しています。その接続には1秒以上かかります。このことを知らないWebアプリケーション開発者が、HTTPリクエストの処理中に誤ってこの関数を呼び出してしまうかもしれません。特に、メールサービスがダウンしていようものなら、ウェブアプリケーションは「ハング」してしまいます。

このような不幸を防ぐために、「実装の詳細」についてコメントを書くべきです。

// メールを送信する外部サービスを呼び出している(1分でタイムアウト)
void SendEmail(string to, string subject, string body);

別の例で、「FixBrokenHtml()」という関数があるとします。これは閉じタグのない壊れたHTMLを修復するためのものです。

def FixBrokenHtml(html): ...

この関数は間違いなく動きます。ただし、対応の取れていないタグのネストが深いと、処理に時間がかかってしまいます。HTMLによっては何分もかかることもあります。

ユーザが使った「あと」で気づくよりも、使う「前」に告知すると、トラブルを防ぐことができます。

// 実行時間は「O(タグの数 * タグの深さの平均)」なので、ネストの深さに気を付ける。
def FixBrokenHtml(html): ...