💣

良いコード・悪いコードを読んで不変の大切さを学んだ!

2022/06/06に公開

概要

業務でPHPを使ってクラスを設計する機会が増えてきたため、そもそもクラスってどう作るのがいいの?という疑問があり、良書と噂されている「良いコード・悪いコードで学ぶ設計入門」を読み進めながら勉強しております。
その中でも、第4章の「不変の活用」のパートが印象に残ったので自分なりにまとめました!!!

結論

再代入(別名:破壊的代入) は、変数の値がコロコロ変わり処理が追いづらく、バグにつながるため、できるだけ不変にするように心がける!

可変の何が悪い?

できるだけ不変にして、何かしらの理由がある場合は可変にすると良さそうだけど、そもそも可変にするリスクって何なのでしょうか?

どこで変数が書き変わったか追いづらい

結論でも述べたように、やはりどのタイミングで変数が変わったのか把握がしづらくなります。
実際、業務でコードを読んでいて「この変数には、今何が格納されてのかな?」と再度、ソースコードを読み直すことがあります。

最悪のケースだと、気づかずにリリースしてデグレに繋がる可能性もあります。
なので、結果的に読み手によくない実装になってしまい、バグにも繋がってしまいます。

可変インスタンスの使い回しによる弊害

クラスのインスタンス変数を可変の状態にしたまま、そのインスタンスを使い回すと予期せぬ箇所でインスタンス変数が連動して変更されてしまいます。

不変にするためのテクニック

それでは、可変を避けて不変にするためのテクニックは何があるのでしょうか?

ローカル変数に修飾子をつけて不変にする

ローカル変数に'final修飾子'などをつけて不変にする。Javascriptの場合だと'const'に当たります。
上記のようにすることで、変数を変更しようとするとコンパイルエラーが発生し、機械的に可変を防ぐことができます。

引数も不変に

引数も同様にfinal修飾子などをつけて不変にします。
もし、引数を変更したい場合は、不変なローカル変数を用意してその変数に変更値を代入するようにします。

インスタンスは使い回さない

インスタンスを使い回さずに、その都度新しいインスタンスを生成するようにします。
そうすることで、それぞれ異なるインスタンスを使用しているため、値が連動して変更されてしまうといった問題を避けることができます。

可変にしてもいいとき

値の変更が頻繁に起こり、インスタンス生成に時間がかかってしまうなどの原因でパフォーマンスに影響が出る場合は、可変にしても良いそうです。

また、パフォーマンス以外だと、ループ時のカウンターや、ループ処理のスコープでしか使用されないようなスコープが局所的なケースも可変にして良い対象になります。

まとめ

クラスを実装する際は、以下を意識するとよさそうです。

  • 基本的に変数は不変にし、やむを得ないときや、スコープが局所的な場合は可変にしても良い。
  • インスタンスは使い回さず新しいインスタンスを生成する。

クラスの実装意外にも普段から変数は不変にすべきと感じました。
実体験としても、可変の変数が多用されていると結構辛いと日々感じながらコードを読んでいるため、実装する際は、不変を意識した実装を心がけようと思います。

また、変数を不変にすることで変数の値を変更する際は、必ず新しい変数を定義する必要があり、その都度命名をつけないといけません。
これは、面倒に思うかもしれませんが、値に変更が加わることは、その値の役割も変わるということです。不変にすることで結果的に、変更後の値に適切な名前をつける機会を与えてくれるのです。
つまり、読み手に優しいコードを自然にかけるということだと思います。

といいつつ、まだまだコーディングの引き出しが足りないので、仕方なく可変にしてしまうこともあるかもしれませんが、できるだけ不変にすることを心がけてコーディングしていきます!!!

Discussion