フィールドとゲッターのコメント
問題
たとえば以下のようなクラスがあったとする。
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に怒られるし・・・
以上、結論がでませんでした。いい案があったら教えてくれ。