Java : コメントが少なくて済むコードを目指そう

ソースコードにどれくらいコメントを書くべきか、なかなか難しいですよね。
本記事では、どういうときにコメントを書くべきか・書かないべきかを解説していきます。


はじめに

コードの意図を補足するためにコメントを書くことは多いと思います。
しかし、コメントを書きすぎていないでしょうか?

理想は、コメントがなくても理解できるコード、だと思っています。

それでは、コメントが不要な例と必要な例を見ていきましょう。

不要な例

コードが何(what)をしているかをコメント

コードが何(what)をしているのかは、コードを見ればわかります。
よって基本的にはコメントは不要です。

極端な例

// valueという変数に2を代入する
final var value = 2;

もう少しマイルドな例

// ファイルを読み込む
final var text = Files.readString(Path.of("data.txt"));

このようなコメントは不要でしょう。
コードだけで十分に理解できます。

クラスやメソッドに機械的にコメント

極端な例

/**
 * Book class
 */
public class Book {

    /**
     * Gets a title
     *
     * @return title
     */
    public String getTitle() {
        ...
    }
}

このようなコメントは不要です。
クラス名やメソッド名がそのままなので、コメントがなくても分かります。

/**
 * 本クラス
 */
public class Book {

    /**
     * タイトルを取得
     *
     * @return タイトル
     */
    public String getTitle() {
        ...
    }
}

日本語にすると、日本人としては少し見やすくなるかもしれませんが、それでも不要だと思います。

もちろん、クラス名やメソッド名からは推測しにくい補足的なコメントは有効です。

public class Book {

    /**
     * 必ず有効な文字列を返します。
     * 空文字を返すことはありません。
     */
    public String getTitle() {
        ...
    }
}

あと参考になるのは標準APIの仕様書でしょうか。

参考:String (Java SE 15 & JDK 15)

ただ、これは多くの開発者に向けた非常に丁寧なコメントです。
通常のプロジェクトではここまでしっかりしたコメントは必要ないと思います。

理想はやはりコメントが少なくても理解できるコードです。

コメントが多く必要なクラスであれば、それはもう少し役割を別のクラスに分割できないか?
コメントが多く必要なメソッドであれば、そのメソッドにいろいろなことを処理させすぎてないか?
という警告でもあります。

必要な例

なぜ(why)そのようなコードにしたのかという意図をコメント

try {
    final var text = Files.readString(Path.of("data.txt"));
} catch (IOException e) {
    // TODO とりあえず例外をキャッチ。
    // 異常系の実装はあとで。
}

とりあえずアプリが動くことを優先して、細かいエラー処理は後回し…ということはよくあるのかなと思います。

そんなときは、"TODO"とともにコメントを残しましょう。
あとで直す予定だから気にしないで!と読み手に伝えることができます。

コメントがないと、IOExceptionを握りつぶしてエラー処理はどうするのだろう?
と読み手に疑問をあたえる可能性があります。

もう1つ例を出します。まずコメントがないバージョン。

public int getAbsValue(int value) {
    final var absValue = Math.abs(value);
    if (absValue < 0) {
        return Integer.MAX_VALUE;
    } else {
        return absValue;
    }
}

getAbsValueは絶対に負数を返さないメソッドとします。
なぜMath.absの結果(absValue)をわざわざif文でチェックしているか分かりますでしょうか?

public int getAbsValue(int value) {
    // Math.absは負数を返すことがあるので注意。
    // Math.abs(int)のドキュメント抜粋
    //   引数がInteger.MIN_VALUEの値(intの最小値)と等しい場合は、結果も同じ値(負の値)になります。
    //
    // MIN_VALUEは仕方ないのでMAX_VALUEを返す。
    final var absValue = Math.abs(value);
    if (absValue < 0) {
        return Integer.MAX_VALUE;
    } else {
        return absValue;
    }
}

こうコメントすると意図が伝わりますでしょうか?
標準APIの名前(Math.abs)からはちょっと推測しにくい挙動ですね。

このように、コードの意図をコメントとすることは有効です。

ただ、それでも書きすぎは注意です。
なぜなら、コメントで補足しないと分かりづらいコード

もっと分かりやすく改善できるコード、ということでもあるからです。

補足

  • Java 15 から Math.absExact が追加されました。
    こちらは、intの最小値を指定すると ArithmeticException が発生するようになります。
    場合によっては、absExactを使う方がよいかもしれません。

メリット

コードだけでは伝わらない内容を補足できます。
特に多人数で開発するような場合は、相手にコードの意図を伝えやすくなります。

デメリット

単純に書く手間がかかります。
そして、メンテナンスが必要なことです。
コメントの対象となるコードを変更したら、コメントも変更しなければなりません。

つまり、コメントを書くのもタダではないということです。

コメントのメンテナンスは、意外と手間で忘れがち。
古くなって、実際のコードとコメントの内容が違っていると、コードの読み手を混乱させてしまいます。
メンテナンスされていないコメントは、削除してしまったほうがまだマシでしょう。

コメントを書かないで済むために一番大事なこと

コメント以外で、コードの読み手に情報を伝える手段があります。

それはクラス名、メソッド名、変数名、といった名前です。
しっかりとした名前をつけてあげれば、自然と読みやすいコードになります。

コメント不要の例として

final var text = Files.readString(Path.of("data.txt"));

というコードを紹介しました。
これは、FilesとreadString、Pathといった名前がしっかりしているので、コメントがなくても処理の内容が推測しやすくなっています。

例えば、同じ処理を、

final var text = Text.getValue("data.txt");

といった名前だと、実際にファイルから読み込むのか?ということははっきりとは分からないでしょう。

名前は大事です。

当サイトの記事「Java TIPS : 標準APIにならう命名規則」も参考にしていただけたら幸いです。

まとめ

コメントは、うまく使えばコードを補足説明できて役に立ちます。
ただ、必要以上にコメントは書かないほうがよいでしょう。

理想は、コメントがなくても理解できるコード、です。


関連記事

ページの先頭へ