はじめに
「良いコード/悪いコードで学ぶ設計入門」を読んでいたのですがその中で、変数をイミュータブルにすることの有用性について説かれていたのでそれをまとめてみました。
使用箇所
本では変数を宣言する際は基本的にfinalを使ってイミュータブルな変数にすべきだと書かれていました。
理由としては以下の二点が述べられていました。
- 変数が本来の意味から逸脱することがなくなるため
変数は値が変わらないことが多いです。
また、変数の値を変えようとするときは別変数に置き換えたほうがいい場合も多いです。 - 影響範囲が限定されるので保守しやすいため
イミュータブルな変数のみでコードを書き、加算などを行う場合は新たなインスタンスを生成してそこに代入するという形を取ることで堅牢なコードが実現できます。
ただし、例外的にミュータブルな変数が認められる場合もあります。
ミュータブルな変数を用いる場合
変数をミュータブルにするときは以下のような場合です。
- 値の変更が膨大になることが予想されるとき
例) ゲームのHPなど - パフォーマンスが求められる場合
例) 計算ごとにインスタンスを生成する時間を削減したい場合など - スコープが局所的な場合
例) ループカウンタなど
また、ミュータブルな変数を用いるときはその変数が不正な状態にならないような設計をすることが求められます。
Pythonでfinalを使う
書籍中ではJavaのfinalを使って説明されていましたが、
Pythonの場合だとPython3.8以降であれば次のようなコードで実装できます。
from typing import Final
hoge: Final[int] = 100
このように記述すると、この後にhogeに対して別の値を代入などをした場合にエディタ上でエラー表示をしてくれます。
ただし、実行時にエラーを出すわけではなくあくまでPythonのFinalは型チェックとしての役割しかないため強制力がないことに注意が必要です。
感想
コードの堅牢さのために変数をイミュータブルにするという考え自体は持っていましたが、
イミュータブルが基本でミュータブルが例外という発想は目から鱗でした。
一方で、Pythonのイミュータブルには強制力がないため今回の考えがマッチするのかと考えると微妙なところです。
参考