Entry

コメントで擬似コードの話とか

2011年01月22日

そういえば,以前「よりそいプログラミングのすすめ」というエントリを書いたんですけれど,そこでこんなコメントをいただきました。

neumann c, programming 中身が固まってたら、まずコメントで疑似コード書くよね? 個人的には変数名を決めるのが作業のボトルネックかな。 2008/12/24

あたしも,とあるところでコメントをコードに置き換える方法を聞いたことがあって,実践していたことがあります。今ではやってないけれど,非常にプログラムが書きやすくなります。

例えば,画像を二値化する関数を作る場合,こんな感じになります。引数は画像(8bpp)のバッファと幅と高さ,それに二値化の閾値です。成功時は0,失敗時は負数を返すことにしましょう。

int
binarize(unsigned char *img, int width, int height, unsigned char thresh) {

  return 0;
}

空の関数はこんな感じになるでしょうか。

実装例は「よりそいプログラミング」のお題と同じような制御構造になるわけで,書ける人はちゃっちゃと書けちゃう種類のものです。もっとも,上の空コードを書いた後どうしたらいいか分からない場合は,次のようにコメントで擬似コードを書いておくといい。

int
binarize(unsigned char *img, int width, int height, unsigned char thresh) {
  // 引数チェック
  // 画素を 1pixel ずつ走査する:
  //   1 pixel 取り出す
  //   画素値が閾値未満だったら,黒を書き込む
  //   画素値が閾値以上だったら,白を書き込む
  return 0;
}

このコメントを,ひとつづつコードに置き換えていけばいいわけです。少しだけ置き換えると,こんな感じになります。

int
binarize(unsigned char *img, int width, int height, unsigned char thresh) {
  // 引数チェック
  if ((img == 0) || (width <= 0) || (height <= 0)) {
    return -1;
  }
  // 画素を 1pixel ずつ走査する:
  for (int i = 0; i < (width * height); ++i) {
    //   1 pixel 取り出す
    //   画素値が閾値未満だったら,黒を書き込む
    //   画素値が閾値以上だったら,白を書き込む
  }
  return 0;
}

取り立てて難しいことはしていません。もう少し置き換えて完成させましょう。

int
binarize(unsigned char *img, int width, int height, unsigned char thresh) {
  // 引数チェック
  if ((img == 0) || (width <= 0) || (height <= 0)) {
    return -1;
  }
  // 画素を 1pixel ずつ走査する:
  for (int i = 0; i < (width * height); ++i) {
    //   1 pixel 取り出す
    if (img[i] < thresh) {
      //   画素値が閾値未満だったら,黒を書き込む
      img[i] = 0x00;
    } else {
      //   画素値が閾値以上だったら,白を書き込む
      img[i] = 0xff;
    }
  }
  return 0;
}

最後に不要なコメントを外してまとめた後,少しだけ最適化します。for-文内の条件判定でいちいち計算するのは無駄なので,走査する総数はあらかじめメモっておくことにしましょう(最適化を有効にしたコンパイラは大抵やってくれるんだけれども)。

int
binarize(unsigned char *img, int width, int height, unsigned char thresh) {
  if ((img == 0) || (width <= 0) || (height <= 0)) {
    return -1;
  }
  // 画素値が閾値未満だったら黒,閾値以上なら白を書き込む
  static const int pixel_num = width * height;
  for (int i = 0; i < pixel_num; ++i) {
    if (img[i] < thresh) {
      img[i] = 0x00;
    } else {
      img[i] = 0xff;
    }
  }
  return 0;
}

これで(大体)おしまい。コメントの粒度は,その人の"分かってなさ"によって変わるので,もっと細かく書かなきゃ置き換えられない人もいれば,もっとざっくり書いても置き換えられる人もいるはずです。もっとも,こゆのは,プログラムを書きまくっているうちに,スニペットととして覚えてしまうもんなので,この程度の制御でいちいちコメントを書くことは普通ないはずです。

一方,コメントを置き換える方法には,次のような弱点があります。「あります」とゆか,個人的にあたしが思っているだけなんですが。

  • 基本的に構造化プログラミングの発想なので,その手の文脈でプログラミングする場合は書きやすいが,他のパラダイム(OOP や関数型)に乗っかってプログラミングする場合は適用しづらい。
  • プログラムの要領を得ない余計なコメントが残る場合が多い(瑣末なコメントが多くできてしまい,コメントの質が悪くなる)。
  • 自然言語をそのまま命令に置き換えるだけで最適なプログラムができることはまずない(最適化する必要がある)。

特に最後の項目は致命的で,この方法の限界を表しています。数理的に複雑なアルゴリズムを実装する場合,こゆ方法はまず採られないと思ったほうが良いと思います。

ま,なにはともあれ,とっかかりを得ることは大事だと思います。まったく書けない人は,試してみるといいかもしれません。

Trackback
Trackback URL:
Ads
About
Search This Site
Ads
Categories
Recent Entries
Log Archive
Syndicate This Site
Info.
クリエイティブ・コモンズ・ライセンス
Movable Type 3.36
Valid XHTML 1.1!
Valid CSS!
ブログタイムズ

© 2003-2012 AIAN