現場で (Java の) String を書き換えざるを得なくなった日、表題のセリフを吐いた我が友人との会話をそれっぽく仕立てたもの。
何語? 意味は?
英語で「不変である」。形容詞。
そこらへんの辞書を引いても出てくるごく普通の単語1そのままで、特別な意味に当てられてるわけではない。
スペルは immutable で、対義語は「変更可能」を意味するミュータブル mutable 2 。
不変って何が? どういうこと?
目の前にダンボール箱があるとする。ガムテープでしっかりと組み立てられている。上面は開いた状態だ。
言うまでもないが、これは簡単に運ぶことができる。そうだろ?
さて、以下にちょっとしたプログラムを用意した。頭のなかで実行してみて欲しい。
- 箱を開ける。
- 箱にものを入れる。なんでもいい。
- 箱を運ぶ。
実行した? では質問だ。
「もし運んでいる最中、その中に土嚢を突っ込まれても平気か?」
えぇ? そんなんありかよ? 普通ないだろ?
そう、さっきの例だと普通ありえないことに思える。しかしプログラムではそういうふうにも書けてしまうんだ。3
そうするととてつもなく話がめんどくさくなる、ってのは想像付くだろ。
そしてプログラミングにおいて、面倒くさいことは大抵バグの原因だ。できるだけ減らさなければならない。
今回の箱の例で言えば、運ぶ前に箱を閉じて、勝手にものが突っ込まれないようにすればいいわけだ。
中身がホイホイ変わるから、考えることが増えてめんどくさくなり、バグの元になる。
なら、変わらないようにすればいい。
これが「不変」のミソなんだ。
うーん……でも、できるのか?そんなこと。
できる。
極端な話、「この名前の変数をいじってはならない」と決めて、それを完璧に守れるなら、それだけで不変は成立する。
要するに「こいつは変わらない」ということをみんながわかっていて、使う時に保証されていればそれでいい。
ただ、現実的にはそうもいかない。大抵どこかの馬鹿が勝手に「書き換えちゃえばいいじゃん!」と馬鹿なことをやりだして崩壊してしまうし、そうでなくとも間違えて書き換える可能性がある。
だから、大抵は手段を講じて不変性の保証を試みる。
だいたいはどっちかだ。
- 言語の機能を利用する。
- 違反を見つけ出しやすい/違反すると面倒なコーディング規約を策定する。
例えば、こういうコードは 不変性を保証しているといえる。
// Java でやる例。不変性を保証するための言語機能が (ややショボいが) 利用できる
// 使うときは final ImmutableExplain ie = new ImmutableExplain(1); とかやるとする
public class ImmutableExplain{
public ImmutableExplain(Integer value){
this.value = value;
}
public Integer getValue(){
return this.value;
}
final private Integer value;
}
このクラスはコンストラクタで (=オブジェクトを作成する瞬間に) 必要な情報を受け取り、自らの中に埋め込み、そして 通常の手段では 触れられないようにしている。おおよそ不変を保証するオブジェクトの典型例と言って差し支えないだろう。
でもそれ、本当にどうしても "不変" じゃ困るってときがでてきたら、どうすんだ?
それは設計がおかしい。が、聞きたいのはそういうことじゃないんだろ。知ってる。
そういうとき、つまり本当の本当にどうしてもその "不変" を侵さなければどうしようもないときは、諦めて書き換えを行う。
できるのかって? できるんだよ。
例えば、例に上げた Java にはリフレクションがある。これは絶対ではないが4、finalフィールドだろうと書き換えることができる。
ただし、それは明らかに通常の手段ではないとわかる方法で、非常手段を取らなければならなかった旨とその理由をコメントで書き残した上で、行われるべきだ。
逆に言えば、本当の本当に不変である、という保証を行うことは事実上不可能だし、必要じゃない。
なぜなら必要なのは普通に使う時、馬鹿により/ミスにより壊されないことを保証することだからだ。immutable は馬鹿の悪影響を減らし、ミスを減らすために存在する、最も有効な手法の一つなんだ。
プログラミング的な注釈
「箱」= 変数。オブジェクト (もっとも、オブジェクトとして考えるとこの「箱」はあまりいいオブジェクトではない) 。
「もの」= 変数に代入される情報。数値、文字列、その他あらゆるデータ。
「閉じた箱」= 中身を書き換えられないようにしたオブジェクト。setter を除去した JavaBean とか、Object.freeze で固めたオブジェクトとか。