🔖

よいコードコメントとは

2023/02/02に公開

TL;DR

  • コメントが多い=丁寧は誤り。
  • コードが表現できていない書き手の意図をコメントに込める。
  • 過剰にコメントが必要な場合はコードの読みやすさが失われていないか疑う。

そのコメントは必要なのか再考する

コメントをどれだけ残すのかは定量化が難しいため、コーディング規約などでは「必要に応じて行コメント(//)を記載する」のような指示となっており、コメントをどこまで記載するかは担当者次第となっています。
コメントを多く記載する人の意図は「コードを読む人にしっかり情報を伝えたい」「コードに自信がない」などさまざまだと思います。
「たくさん書いておいたほうがいい!!」という人もいるでしょう。
ここではどのようなコメントが必要・不必要であるか、いくつか例を紹介したいと思います。

コードが説明できていることはコメントしない

不要なコメントの例を次に示します。

// ユーザ情報から氏名を取得して営業担当者DTOに設定する
salesDto.setFullName(userInfo.getFullName(id));

このように明確な命名がされていて意図が明確な場合、コメントは不要です。

コード内の命名や実装を再検討する

次に示す例は現場で実際に実装されていたコードです。
画面のチェックボックスのチェックの有無でふるまいを変える処理です。

boolean chkFlg = false;
for (SendForm sendForm : form.getSendFormList()) {
  if (sendForm.isSelectChecked()) {
    // チェックありの場合、true。1件でもチェックありだったら処理を抜ける
    chkFlg = true;
    break;
  }
}
// chkFlgがfalseだったらエラー
if (!chkFlg) {
  param.setMsgInfo(new MessageInfo(MessageCd.A1001E, "選択チェック"));
  param.setResultCd(ResultCd.ERROR);
  return;
}

適切な命名でも同じコードを利用しましたが、このコードではchkFlgの命名が適切でないためにコメントが必要になっています。
命名が適切に行われていれば、コメントは不要です。
また、「チェックありの場合、true。1件でもチェックありだったら処理を抜ける」も動作を見れば分かるので不要です。

実装の意図を説明する

ひとつ前の例のコメントを外してみましょう。(変数名も変更)
すっきりしましたが、ループの意図が少しわかりずらいと感じます。

boolean checkedItemExists = false;
for (SendForm sendForm : form.getSendFormList()) {
  if (sendForm.isItemChecked()) {
    checkedItemExists = true;
    break;
  }
}

if (!checkedItemExists) {
  param.setMsgInfo(new MessageInfo(MessageCd.A1001E, "選択チェック"));
  param.setResultCd(ResultCd.ERROR);
  return;
}

意図を説明するために次のようにコメントします。

boolean checkedItemExists = false;
// 送信相手が最低1つ選択されているか検索する
for (SendForm sendForm : form.getSendFormList()) {
  if (sendForm.isItemChecked()) {
...

大切なのはコードでは表現できていない意図を説明することです。

良い例を参考にしてみる

インターネットには著名な会社や開発者による多数のコードが公開されています。
参照することでどのような時にコメントが採用されているか、学ぶことができます。

GoogleのJJSONコンバーターgoogle/gson - JsonReaderを覗いてみましょう。(コメントは簡単に翻訳しています)

  ...
  /** 仕様に準拠しないJSONを受け入れる場合はTrueを指定 */
  private boolean lenient = false;

  static final int BUFFER_SIZE = 1024;
  /**
   * これから読む文字や未読の文字を簡単に読み取るため、
   * また、中間的なStringBuilderを使わずに文字列を作成するため
   * 手動バッファを使用する。
   * このバッファから直接リテラルをデコードするため、少なくとも
   * 数値として報告できる最長のトークンと同じ長さが必要。
   */
  private final char[] buffer = new char[BUFFER_SIZE];
  private int pos = 0;
  private int limit = 0;

  private int lineNumber = 0;
  private int lineStart = 0;
  ...

ここでは命名から用途が明らかであるposlimitlineNumberlineStartBUFFER_SIZEはコメントされていません。
命名からは想像が難しい変数についてはコメントが記載されています。

コーディング規約には従う

ユーザー先でコーディング規約が整備されている場合があります。
その準拠はプロジェクト開始時合意しています。
コーディング規約でコメントが必要とされている場合は不要と思われるケースでも記載するようにしてください。

まとめ

  • コードコメントは多いからいいということはない。
  • コメントに頼るのではなく、読み手が分かるコードを意識する。
  • それでも伝えきれない場合はコメントに動作ではなく意図を込める。
  • コーディング規約がある場合は是非を問わず従う。
株式会社ソルクシーズ(事業戦略室)

Discussion