コメントからはじめよう

ソフトウェアエンジニアには「設計力と実装力のバランスをとることが大切」と教えてもらいましたけど、実装力(細部までキッチリと作り上げる力)を伸ばすには、どうしたらいいですか?
そうねぇ。まずは一つ一つの関数をキッチリ仕上げられるように気を付けることかしら。
一つ一つの関数をキッチリ……ですか。
そうよ。……あら、なんか「納得いかない」って顔ね。
いえいえ、そういうわけじゃないんですけど……その、キッチリっていうのがいまいちピンとこないんですよ。
ああ、そういうことね。……それじゃあ、まずは「キッチリした関数」とはどんなものかという定義を考えてみましょう。
はい!

関数がキッチリしていると言える条件は、以下のような仕様が細部までしっかりと明確になっていることです。

キッチリした関数とは

  • 使用目的が明確
  • 定義域(受け付けられる入力の範囲)が明確
  • 値域(得られる出力やエラー値の範囲)が明確
  • 制限事項が明確

なるほど。関数を実装するときには、こういう細かい仕様をきちんと考えておく必要があるってことですね!
そういうこと。
だけど、最初は意識していたつもりでも、実装を考えているうちに忘れてしまうこともありそうですね……
そうなのよ。だから、関数のコーディングを開始する前に、仕様について「コメント」を書いておくのがおすすめよ。
え、コメントですか!?しかもコーディングの前に!?

細かいところまで漏れなく仕様を決めて、「キッチリした関数」を実装するためのガイドラインは、「コメントを書く」ことです。関数のコーディングを開始する前に、その仕様についてコメントしましょう。

コーディングしながら書くのではなく、コーディングしてから書くのでもなく、コーディングする前に書くのです!

どんなコメントを書くのがおすすめですか?
それじゃあ、具体的にどのようなコメントを書けばいいのか、一つずつ考えていきましょう。

使用目的

関数の使用目的は、言葉で表現するのが一番よ。普通に日本語で書けばいいわね。

関数の使用目的を書くのは、何を作ったのかを忘れないようにするためだけではありません。

明確に言葉で表現することによって、これから作ろうとしているものを自分自身に言い聞かせるためでもあります。実際に言葉で書いてみると、何を作るか分かっていたつもりでも、実は考えがまとまっていないことに気付くかもしれません。

なるほど。すごく身に覚えがあります。

そういう意味でも、関数を一つ書く前に、その目的についてコメントするのはおすすめの習慣です。

頭の中がモヤモヤしたままでコーディングを始めるよりも、欲しいものをハッキリさせてから作ったほうが品質も期待できるわね。

ちなみに、関数の使用目的は「作る人」ではなく、「使う人」の視点で書けるとベターです。どの関数も作るのは1回きりなので、使うためにコメントを読む回数のほうが多くなるからです。

定義域

関数が入力できる値の範囲は、明確に記述する必要があるわね。

例えば次の関数(文字列の長さを求める標準関数ですね)は、引数に0(NULL)を指定することができません。

size_t strlen(const char *s);

このように、関数には入力できる値とできない値があるのが普通です。想定外の値を入力すれば、プログラムはクラッシュしてしまうかもしれません。

では、このことがコメントされていなかったら何が起こるでしょうか。

例えば、この関数のある利用者が「0を入力するとクラッシュするぞ」という「発見」をしたとしましょう。このとき、コメントに何も書かれていなければ、「これは関数のバグだろう」と判断するかもしれません。

その結果、クラッシュしないように関数の実装を手直ししたとしたら、これは「デバッグ」でしょうか?いいえ、この行為は紛れもなく仕様変更です!

この例の問題点は、クラッシュした理由が関数の実装のせいなのか、使い方のせいなのかが不明なことよ。

もしも関数の定義域がコメントされていれば、どちらが間違っているのかすぐに分かったでしょう。このようなコメントには、安易な仕様変更を抑止する効果があるのです。

なるほど〜。

ちなみに、実際に関数をコーディングするときは、範囲外の入力を受け取ったらassertすればいいですね。

assert()については別のトピックで詳しく説明します。

値域

値を返す関数では、その範囲を明記しておくことも大切ね。

以下の2点について、しっかり書いておきましょう。

  • 正常な値:関数が正常に終了した場合に返却する値の範囲
  • エラー値:関数がエラーになった場合に返却する値の範囲

エラー値は、関数を呼び出したあとの判定に必要な情報です。ファイル操作やメモリー確保など、ある程度の確率で発生するエラーの確実なチェックを促すためにも、ぜひコメントしておきましょう。

制限事項

その関数でできないことがあれば、それも明記しておきましょう。

例えば、文字列の文字数をカウントする関数には、次のような制約があるかもしれません。

  • 「この関数は、文字列がUTF-8でエンコードされているものとして扱います」

こうした記述があれば、関数が不可解な動作をしたときに、頭を悩ませる時間を節約できるでしょう。


ふむふむ。あらかじめコメントを書いておくと、いろいろな場面で役立つんですね。
そういうこと!

関数を作る前に仕様をコメントするのは、正直に言えば面倒臭い作業です。でも、それ以上に効果が期待できます。コメントを書くのに時間がかかっても、トータルでは時間の節約になるのではないでしょうか。

ここがポイント!
関数のコーディングを開始するときは、コメントを書くことからはじめましょう。細かい仕様まで明確にしておけば、キッチリ仕上げられます。

次のトピックでは、あとで関数を使う人(または使うとき)のために何をやっておくべきか検討しましょう。