最近、オブジェクト指向プログラミング(OOP)でありがちなバグの原因って、知らないうちに「状態」が変わっちゃうことが多いって知ったんだよね💭
たとえば、あるオブジェクトの中身を勝手に変えられちゃって、あとで「あれ?思ったのと違う!」みたいなこと、経験ない?😳
それを防ぐために最近注目されてるのが、「Immutable by Default(最初は不変にする)」って考え方✨
Immutableってなに?
Immutable(イミュータブル)っていうのは、「一度作ったら変えられない」って意味なんだ🥺
たとえば、写真みたいなもので、一回撮ったらそのまま変わらない感じ。
逆にMutable(ミュータブル)は「変えられるもの」ね。
普通の変数やオブジェクトはこれが多いけど、それが原因でバグが生まれやすいんだって👀
どうしてImmutableにするの?
オブジェクト指向の世界では、いろんなオブジェクトが協力して動くから、どこかのオブジェクトの状態が意図せず変わると、全体の動きがおかしくなることがあるんだよね💭
これって言わば、みんなで共有してるノートに誰かが勝手に書き換えちゃうみたいなイメージで、あとで「あれ?何で変わってるの?」ってなっちゃうのが怖いところ⚠️
だから、最初から「変えられませんよ」ってルールを作っちゃおう!って発想がImmutable by Default✨
具体的にはどうするの?
-
データを作ったら変更しないクラスを作る
→ メンバー変数をfinal
にしたり、setterをなくしたりして変更不可にする👗 -
もし変更が必要なら、新しいオブジェクトを作る
→ 変えたいところだけ新しくして、元はそのままキープ🍓 -
読み取り専用のメソッドだけを公開する
→ 外から中身をいじれなくしておくことで安心感アップ🧠
これのメリットって?
-
バグが見つけやすい・起きにくい
変なところで状態が変わらないから、原因調査がラクになるし予測もつきやすい✨ -
コードがシンプルで安全
誰かが勝手にデータいじって混乱する心配が減るから、みんなでコードを共有しやすいよ👍 -
テストも楽になる
変わらないから、一度のテスト結果が信頼できるってわけ💡
でも、全部をImmutableにしたら重くならない?
確かに、全部を変えられないものにすると新しいモノを作りまくるから、処理が遅くなるんじゃ…?って思ったけど、実際はそんなに気にしなくていいみたい✨
理由は、最近のプログラミング言語やライブラリは賢くて、効率的にコピーや共有をしてくれるからだって💭
もちろん、使いどころは考えないとだけど、重要な部分はまずImmutableでいくのが安心ってことみたい🥺
オブジェクトの状態がコロコロ変わるのって、気づかないうちにバグを生みやすいモヤモヤポイントだったんだなぁって思ったよ💭
「最初から変えられない」って決めちゃうことで、トラブルの芽を減らすって考え方、ちょっと試してみたくなったかも✨
プログラムの見えない部分が整理されると、なんだか気分もスッキリするから不思議だよね🥺💗
コメント
クリス
状態を全部マッピングしてみた? 「隠れた状態」問題ならそれで見える化できるよ。
グレース
関数型言語はパワーのほんの一部を真似するのに苦労してるよね。
ハンナ
純粋関数を書けば?
ノーラン
問題は変更可能性じゃなくて参照を使うこと。 コピーすればいいのに。
ロバート
C#のRecordはイミュータブルで、修正コピーも簡単で最高だよ。
ノーラン
君の例のバグ直したけど、DateTimeのAPI作ったやつはマジで怒るべきだ。
ハンナ
無理やりイミュータブルにしてるせいでDDDが変なことになってるの見てきたよ。
ベン
AI以外の話題でちゃんとプログラミングの話ができるのは新鮮だね。
リリー
constの概念や値セマンティクスがない言語はやっぱり問題多いよ、C++は別だけど。
グレース
共有参照は変わるものって覚悟しないとね。 定数が欲しいならコピーを持てばいい。
ハンナ
OOPでクラスをイミュータブルにすると意味が薄れて、専門用語で「貧血モデル」って言われるよ。
キンバリー
Swiftは値型と参照型を使い分けてうまく解決してる。
ノーラン
これは状態の問題じゃなくてデータ破損の問題だよ、変更されちゃいけないデータなんだ。
クリス
OOPの本読み直すべきで、オブジェクトは関数経由で操作するのが基本だよ。
ロバート
新卒時代はOOPに夢中でセット理論と並行処理に強かったけど、結局大事なのはチームがメンテできることだと気づいた。
ミア
結局は「機能的コア+命令的シェル」が最強で、OOもそれに合わせて使うべきだよ。
グレース
イミュータブルの一番いいところはスレッドセーフってとこだね。