イミュータビリティとは?決して変わらないデータ
イミュータビリティとは、一度作られた値は変更できず、あらゆる更新が元をその場で書き換える代わりに新しい値を生み出すことを意味します。
ミュータブルなデータは生成後に変更でき、柔軟ではありますが、プログラムの多くの部分が同じオブジェクトを共有して書き換えるときにバグの頻繁な原因になります。イミュータビリティはこれを反転させます。データは一度作られると読み取り専用になり、「変更」は差分を適用した新しいコピーを返します。元は手つかずのままで、これによりプログラムは推論しやすく、並行処理下でより安全になります。
イミュータビリティが実際に意味すること
イミュータブルなデータでは、オブジェクトを決して変更せず、変更を反映した新しいものを作ります。古いバージョンは依然として存在し、依然として有効です。それへの参照を保持するものは何であれ、他のコードが何をしようと、安定した不変の値を見ます。
イミュータビリティがバグを減らす理由
- 遠隔からの不気味な作用がない: 他の何もあなたのデータをmutateできない。
- スレッド間での安全な共有: イミュータブルなデータには競合がないため。
- 参照の比較による容易な変更検出: 深い内容の比較ではなく。
- 推論とテストがしやすい予測可能なコード。
イミュータビリティと並行処理
競合状態は共有されたミュータブルな状態から生じます。共有状態がmutateできなければ、競合するものは何もありません。これが、イミュータブルなデータが安全な並行・並列プログラミングの中心である理由です。
イミュータビリティのコスト
mutateする代わりに新しい値を作ることは、より多くのメモリと割り当てを使い得ます。永続データ構造と構造共有は、変わらない部分を再利用することでこのオーバーヘッドを減らしますが、イミュータビリティは無料ではありません。
手短な例
JavaScriptでは、const next = [...arr, item] は arr をmutateする代わりに新しい配列を構築します。元はそのままで、next は別の値です。
CIにおけるイミュータビリティ
共有fixtureをmutateするテストは互いを汚染し、順序に応じてpassしたりfailしたりし得ます。これは古典的なflakyテストの原因です。イミュータブルなテストデータは各テストを隔離したままにします。Latchkeyは一時的な障害を自動でリトライしつつ、あなたは共有ミュータブル状態のflakinessをスイートから取り除けます。
重要なポイント
- イミュータビリティとは値が決して変わらず、更新が代わりに新しい値を作ることである。
- 共有されたmutationを取り除くことで多くのバグを排除し、並行コードを安全にする。
- いくらかメモリを消費するが、永続データ構造の構造共有によって緩和される。