- PR -

変更しない変数にfinalを付けるべきですか?

投票結果総投票数:69
必須 2 2.90%
望ましい 25 36.23%
場合による 7 10.14%
どっちでもいい 1 1.45%
付けなくていい 28 40.58%
付けないほうがいい 4 5.80%
付けるな 0 0.00%
絶対に付け 2 2.90%
  • 投票は恣意的に行われます。統計的な調査と異なり、投票データの正確性や標本の代表性は保証されません。
  • 投票結果の正当性や公平性について、@ITは一切保証も関与もいたしません。
投稿者投稿内容
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-04-04 16:40
引数にインスタンスを渡す場合、
・状態の変更可能なインターフェイスの隠蔽
・クローンを渡す
というのがよくあるパターンかと思います。

状態の変更可能なインターフェイスの隠蔽ですが、
コード:
interface Hoge{
    String getPiyo();
}

class HogeImpl implements Hoge{
    String piyo;

    String getPiyo(){
        return piyo;
    }

    void setPiyo(String piyo){
        this.piyo = piyo;
    }
}


と、読み込み専用のインターフェイスを用意して、
実装で書き込みをできるようにします。
渡す場合は、
コード:
void foo(Hoge hoge);


というメソッドを用意すれば変更可能なインターフェイスが隠蔽されます。

クローンを渡すというのはフィールドの配列を返すときに、
フィールドが参照している配列ではなく、
その配列のクローンを返すということをよくやると思いますが、同じことです。
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2007-04-04 16:59
unibonさん、かつのりさん、ありがとうございます。

【unibonさんのコード例】
普通にオブジェクト指向開発してきた人なら、まずそう考えますよね。

しかし、うちのプロジェクトのコードをよくよく見てみると、
値を二つ以上返したいときに、メソッドの中で書き換えちゃうみたいです。

最初は、値を変更しませんよというアピールのためにだけでも、
付けても害はないかなとも思っていましたが、

結局、開発者の良識に任せるしかないのなら、
final付ける意味ってないような。。。ホント、徒労ですね。

【かつのりさんのコード例】
かっちり、決めたいときはそうしたいですね。

しかし、interfaceを使うとは考えつきませんでした。
単にsetterを隠蔽するのかと。。。

これって、ナントカ指向かなにかっぽいですね。
# インターフェイスドリブンかな?

さっそく、いただいちゃいます!

ところで、かつのりさんはどうして
「コンパイルエラーが出ない限り、絶対に付けるな!!」じゃないんですか?
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2007-04-04 16:59
引用:

あぶぽんさんの書き込み (2007-04-04 15:36) より:
最近、うちのプロジェクトにCheckStyleが導入され、
ウォーニング消しにあくせくで、手がつりそうです。。。

僕がどうこう言える立場ではないのですが、
特に気になるのは、変更しない変数にfinalを付けさせることです。
やたら多いので困っていますが、チェックから外す方針はないそうです。


CheckStyle は使ったことがないのですが、final が付いていないと警告が出るということでしょうか。警告ツールが警告を出すから、一律に final を付けるというのは、機械に人間が使われているようであり、本末転倒だと思います。私だったらその「チェック」から外します。
(もっとも、私も、普段は、eclipse のコンパイラーの警告は強め(警告がたくさん出るように)にして、出た警告はせっせと消します。しかし final を付けようとは思いません。)

引用:

あぶぽんさんの書き込み (2007-04-04 16:20) より:
引用:

付けることに手間と時間をかけるのは、手間と時間がもったいないから
「付けないほうがいい」です。



手も時間もたっぷりとあるとしたら付けたほうがいいですか?


たっぷりあったら、ほかのこと(もっと有意義なリファクタリングや休憩)に使ったほうが良く、やはり final は付けないほうがいいと思います。

--
unibon {B73D0144-CD2A-11DA-8E06-0050DA15BC86}
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-04-04 17:10
付けなくていいに一票入れました。

すでに前の書き込みにあるように、
インスタンスの中身を書き換えない事を保証するには
引数となるクラスの側がimmutableでなければならないからです。

引数とローカル変数の寿命はメソッド内だけなので一目瞭然ですし。

クラス変数/インスタンス変数の場合は積極的にfinalにしています。
寿命の長いオブジェクトの状態管理は思っているより難しいものです。
可能であるのならimmutableにしてしまいます。
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2007-04-04 17:15
unibonさん、

CheckStyleのfinal警告は、以下のようなコードも
finalが必要と言われるんですよ!

コード:

SampleClass sample1 = new SampleClass();
sample1.setAttribute1(value);



たしかに、sample1変数(アドレス値)は変わってないのですが。。。


[ メッセージ編集済み 編集者: あぶぽん 編集日時 2007-04-04 17:21 ]
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-04-04 17:33
独り言です。

どこかで仕様案が出ているかもしれませんが、アノテーションもしくは
マーカインタフェースでImmutableを表現できると良さそうな気がします。

コンストラクタ以外ではインスタンス変数を全てfinalと同様に扱う仕様で。
互換性を考えるとVMではなくコンパイラレベルで行うのが妥当でしょう。
#もしかしたらC++のmutableみたいなものが必要になっちゃうかも?

rubyのfreeze()のようにタイミングを選べるのも便利ですね。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-04-04 17:40
私の場合は単純に、目的に合う場合にのみにfinalを付ける派ですね。
目的外なら付けません。面倒なので。

私もFindBugsを使って警告にしたがって修正もしますが、全てではありません。
CheckStyle主義すぎるのも、いかがなものかと思います。
あぶぽん
大ベテラン
会議室デビュー日: 2005/10/20
投稿数: 205
投稿日時: 2007-04-04 18:07
僕の場合は、finalを使うのは定数とアクセッサだけと決めています。
(アクセッサに付けるのは、コンパイラにインライン展開をお願いするため)

だから、finalの手戻りが大きいんですよね。。。
CheckStyleが悪いわけではありません。設定ではずせるのですから。

しかし、目の前の仕事から逃げるわけではありませんが、
前述のとおり、参照型の変数にはすべてfinalを付けることになります。
(値は変わっても、参照元アドレスは変わらないので)

。。。美しくないという理由もあってもいいかと思います。

スキルアップ/キャリアアップ(JOB@IT)