読者です 読者をやめる 読者になる 読者になる

コメントつけろよ

プログラマは自分でコードを書くことができるだけでなく、他人が書いたコードを (ある程度は) 読むことができなければなりません。 その際に最もゲンナリさせられるのが、コメントが全くないソースコードです。

腕の立つプログラマのコードというのはきちんと構造化されいるため、コメントに頼らずとも作者の意図をきちんと読み取ることができます。 しかし、そのようなコードを書くプログラマは、コメントもきちんと付けるもの。 むしろ、初心者や読みづらいコードを書くプログラマほど、コメントも疎かになる傾向があるようです。
彼らが自分のソースコードにコメントを付けない理由として挙げるものとしては、

  • 時間がなかったから。(急いで修正したから。)
  • 公開するつもりのないコードだから。
  • コメントを付けると、コメントに頼ってコードを読むようになってしまうから。
  • コメントを入れるのと、素人のコードっぽく見えるから。
  • コードの可読性は品質には影響しない。可読性をあげて良いことがあるのか?
  • などなど……。(いずれも、実際に言われたことがある。)
    人それぞれに事情や主義主張があるのは分かりますが、正直「そのコードの保守運用をさせられるこっちの身にもなってくれ」と言いたくなります。(そして、実際に言っています。^^;)

    コメントのないコードの例

    次に示す関数は、西暦 1年 1月 1日からの経過日数から日付を計算し、yyyy/mm/dd の形式で表示するものです。
    紀元前の日付や閏年も考慮に入れているため、なかなかに複雑なコードになっています。
    それにも関わらず、コメントが一切ないので読みづらいことこの上ありません。
    このコードを読め (あるいはデバッグしろ) と言われたら、誰だって (´д`;)エェー となるのではないでしょうか。

    const int MONTH_DAYS[] ={
    0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    const int MONTH_DAYS_BHX[] ={
    0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    bool bissextile(int y){
    assert(y);
    return !(y % 4) && (y % 100 || !(y % 400));
    }
    void printDate(int nIdentity){
    if (nIdentity >= 0){
    int y =1;
    int m =JAN;
    for (;;){
    if (bissextile(y)){
    if (nIdentity < 366){
    while (nIdentity >= MONTH_DAYS_BHX[m]) nIdentity -=MONTH_DAYS_BHX[m++];
    break;
    }
    nIdentity -=366;
    }
    else {
    if (nIdentity < 365){
    while (nIdentity >= MONTH_DAYS[m]) nIdentity -=MONTH_DAYS[m++];
    break;
    }
    nIdentity -=365;
    }
    ++y;
    }
    printf("%04d/%02d/%02d\n", y, m, nIdentity + 1);
    }
    else {
    nIdentity =-(nIdentity + 1);
    int y = -1;
    int m =DEC;
    for (;;){
    if (bissextile(y)){
    if (nIdentity < 366){
    while (nIdentity >= MONTH_DAYS_BHX[m]) nIdentity -=MONTH_DAYS_BHX[m--];
    printf("%04d/%02d/%02d\n", y, m, MONTH_DAYS_BHX[m] - nIdentity);
    break;
    }
    nIdentity -=366;
    }
    else {
    if (nIdentity < 365){
    while (nIdentity >= MONTH_DAYS[m]) nIdentity -=MONTH_DAYS[m--];
    printf("%04d/%02d/%02d\n", y, m, MONTH_DAYS[m] - nIdentity);
    break;
    }
    nIdentity -=365;
    }
    --y;
    }
    }
    return;
    }

    コメントを入れてみる

    では、このコードにコメントを入れてみましょう。
    どれだけ読みやすくなるかを、自分の目で確かめてください。

    //月の日数 (平年用)
    const int MONTH_DAYS[] ={
    0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    //月の日数 (閏年用)
    const int MONTH_DAYS_BHX[] ={
    0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
    };
    //閏年の判定
    bool bissextile(int y){
    assert(y);
    return !(y % 4) && (y % 100 || !(y % 400));
    }
    //日付の計算・表示)
    void printDate(int nIdentity){
    if (nIdentity >= 0){
    //紀元 (A.D.) ----------------------------------------------------------
    //西暦元年 1月から開始
    int y =1;
    int m =JAN;
    //1年未満になるまで、日数を引く
    for (;;){
    if (bissextile(y)){
    //閏年の場合
    if (nIdentity < 366){
    while (nIdentity >= MONTH_DAYS_BHX[m]) nIdentity -=MONTH_DAYS_BHX[m++];
    break;
    }
    nIdentity -=366;
    }
    else {
    //平年の場合
    if (nIdentity < 365){
    while (nIdentity >= MONTH_DAYS[m]) nIdentity -=MONTH_DAYS[m++];
    break;
    }
    nIdentity -=365;
    }
    ++y; //1年先 (未来) へ
    } // for(;;)
    printf("%04d/%02d/%02d\n", y, m, nIdentity + 1);
    }
    else {
    //紀元前 (B.C.) --------------------------------------------------------
    nIdentity =-(nIdentity + 1);
    //紀元前 1年12月から開始
    int y = -1;
    int m =DEC;
    //1年未満になるまで、日数を引く
    for (;;){
    if (bissextile(y)){
    //閏年の場合
    if (nIdentity < 366){
    while (nIdentity >= MONTH_DAYS_BHX[m]) nIdentity -=MONTH_DAYS_BHX[m--];
    printf("%04d/%02d/%02d\n", y, m, MONTH_DAYS_BHX[m] - nIdentity);
    break;
    }
    nIdentity -=366;
    }
    else {
    //平年の場合
    if (nIdentity < 365){
    while (nIdentity >= MONTH_DAYS[m]) nIdentity -=MONTH_DAYS[m--];
    printf("%04d/%02d/%02d\n", y, m, MONTH_DAYS[m] - nIdentity);
    break;
    }
    nIdentity -=365;
    }
    --y; //1年前 (過去) へ
    } // for(;;)
    }
    return;
    }

    このようにコメントが付けられていれば、プログラマの意図がコード中に明示されるため、読む側は頭の中で流れを整理しやすくなり、バグの特定なども容易になります。