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

フィールドとゲッターのコメント

Java

問題

たとえば以下のようなクラスがあったとする。

class Blog{

  //ブログの更新日時(UTCミリ秒)
  private long updateTime; 

  //...(ここに5000行のコード)...

  /**
   * ブログの更新日時(UTCミリ秒)を返します。
   */
  public long getUpdateTime(){
    return updateTime;
  }

よく見かける、privateフィールド+ゲッターメソッドをもったクラスである。で、ちょっとコードのコメント周りを見てみると、なんか「ブログの更新日時(UTCミリ秒)」というまったく同じコメント文字列が2箇所に記述されていることに気がつく。3ヵ月後、親切な新米エンジニアの義彦くんが、フィールドのコメントをより厳密に修正してくれたとする。

class Blog{

  //ブログ全体の最終更新日時を、エポックからのUTCミリ秒値で表したもの
  private long updateTime; 

  //...(義彦は忙しいのでこれより以下のコードは読んでいない)...
  //...(ここに5000行のコード)...

  /**
   * ブログの更新日時(UTCミリ秒)を返します。
   */
  public long getUpdateTime(){
    return updateTime;
  }

すると、どうだろう。フィールドのコメントと、getterのコメントに相違が発生してしまった。幸い修正点はコメントの部分だけなので、プログラムの動作には影響はないはずである。しかし、私のような神経質なエンジニアは、このコードに少なからず嫌悪感を感じてしまう。

さて、このような事故(?)を防ぐにはどうしたらいいか。

解決策1:フィールドをもっとわかりやすい名前にする

そもそもupdateTimeというフィールド名がよろしくない。フィールド名は、このフィールドが何を意味するのかをもっと明確に主張すべきである。そこで以下のように修正する。

class Blog{

  private long updateTimeInThisBlogAsUtcMiliSecFromEpocTime; 

  //...(ここに5000行のコード)...

  public long getUpdateTimeInThisBlogAsUtcMiliSecFromEpocTime(){
    return updateTimeInThisBlogAsUtcMiliSecFromEpocTime;
  }

やった!諸悪の根源であるコメントを消すことができたぞッ!・・・うむ〜。

解決策2:getterのコメントは不要

おなじコメントが2箇所にあるなんてDRYじゃないッ!getterにコメントなんて不要!

class Blog{

  //ブログ全体の最終更新日時を、エポックからのUTCミリ秒値で表したもの
  private long updateTime; 

  //...(ここに5000行のコード)...

  public long getUpdateTime(){
    return updateTime;
  }

悪くない。しかし、これだとjavadocを生成した際に問題が発生する。javadocでは普通privateフィールドに関する説明文は表示されないので、せっかく書いたコメント文がjavadocからきれいさっぱり見えなってしまう。

追記:
karugamo氏いわく:
フィールドはしょせん内部参照しかないので、影響範囲が作った本人になるけど、メソッドは、意味を履き違えると他人と大きな誤解を生むので、こっちは気をつけてます。

解決策3:いやいやフィールドのコメントこそ不要

privateフィールドは、当該クラス内からしか参照しないわけだし、むしろgetterメソッドのコメントを充実させるべき!

class Blog{

  private long updateTime; 

  //...(ここに5000行のコード)...

  /**
   * ブログの更新日時(UTCミリ秒)を返します。
   */
  public long getUpdateTime(){
    return updateTime;
  }

これだとjavadocの問題は解決する。さらにEclipse等を使っていれば、getUpdateTime()を呼び出している箇所にマウスカーソルを合わせると、ポップアップでコメントを表示してくれたりして、さらにうれしい。でも、Blogクラスを編集するときは、フィールドにコメントが書いてあったほうがわかりやすいよなぁ。。オブジェクト自身からフィールドの値を参照するときは、普通getterじゃなくて、直接フィールドを参照するよねぇ。。。

何が問題か

結局、フィールドとgetterが分離しちゃってるところに問題があるのな。フィールドのアクセサーを定義するキーワードが用意されている言語であれば以下のように書ける。

class Blog
  //ブログ全体の最終更新日時を、エポックからのUTCミリ秒値で表したもの
  updateTime; 
  attr_reader :updateTime

  //...(ここに5000行のコード)...
end

あー、javaでもフィールドとgetterを並べて書けばいいのか。

class Blog{

  private long updateTime; 

  /**
   * ブログの更新日時(UTCミリ秒)を返します。
   */
  public long getUpdateTime(){
    return updateTime;
  }

  //...(ここに5000行のコード)...

たまに見るよね、こういうコード。でもこれだとたぶんFindBugsに怒られるし・・・

以上、結論がでませんでした。いい案があったら教えてくれ。