Javaも変数をデフォルトで不変にできないかなと思った話
作成日時:2023-02-05
更新日時:2024-02-05
Rustの “変数は標準で不変” という仕様が気に入った
変数と可変性 - The Rust Programming Language日本語版
https://doc.rust-jp.rs/book-ja/ch03-01-variables-and-mutability.html
Javaでもそういうことができそうなライブラリは無いかな~と思って探してみたが無さそう。
「自分で全ての変数にfinalつければいいだけじゃん」と言えばそうだが
そんなの可読性が下がるしコーディングも面倒なので、そういったものは自動でやってもらいたい。
なので、クラスにアノテーションをつけたら内部のローカル変数定義が全部final扱いになるライブラリを作る事にした。
ライブラリを作るにあたって、参考にLombok(アノテーションを使ってgetter/setterとかを自動生成するライブラリ) の中身を見てみた。
Lombokでそういうのが既に実装されてた
既にあるんかい。
検索の仕方が悪かったか。
不変のローカル変数はvalで変数定義。
https://projectlombok.org/features/val
2年前に実装されたっぽい。
Lombokはgetter/setterの自動付与ぐらいにしか使ってなかったが、結構いろいろなことができるのね。
https://projectlombok.org/features/
使い慣れたライブラリや言語でも定期的な再学習は必要だなあと思った。
というオチ。
再代入不可能性と言語仕様に関して
変数と可変性 - The Rust Programming Language日本語版
https://doc.rust-jp.rs/book-ja/ch03-01-variables-and-mutability.html
から引用
Rustでは、値が不変であると宣言したら、本当に変わらないことをコンパイラが担保してくれます。 つまり、コードを読み書きする際に、どこでどうやって値が変化しているかを追いかける必要がなくなります。 故にコードを通して正しいことを確認するのが簡単になるのです。
個人的に思ったこと箇条書き:
- (引用)どこでどうやって値が変化しているかを追いかける必要がなくなります。
→この思想は好き。再代入されるのが個人的に好きじゃないから。 - 変数を使用する直前に定義させるよう誘導できるのでは。
→上手く説明できないけどなんかそんな気がする。下記のようなクソコードは書けなくなるでしょ。
(まあ1行目で初期化されたらそれまでだが、そういうのはコーディング規約やチェックリストを策定し書かせないようにする。)
Foo foo = null;
…
(数百行のコード)
…
// 初めて初期化 + 使用。
foo = new Foo(); // 不変ならここでエラーになるので、使用する直前のここで変数定義をやらざるを得ない。
foo.method();
- 個人的にJavaScriptだったら
(モダンなJavaScriptの案件に入ったことがないので、実際の現場ではどうあるべきかよくわからないが)
変数定義は基本的にconstを使いたい。 - Javaはいちいちfinalを書くのが面倒だからローカル変数は仕方なく可変にしておくけど。
(定数定義にはもちろんfinalを付ける。定数だもの。) - Scalaもvar / valがあるっぽい。
- 話が変わるけどGoとかの最近の言語は、言語仕様そのものが可読性をあげるようになっているの好き。
※Software Design 2月号のGoの解説記事を読んでこの思想を知った。
2月号から始まった連載記事でしばらく続くようだから、Goに興味がある人は読むのもいいかもしれない。
7ページ位だから本屋で立ち読みでも。