プログラミング

イミュータブルプログラミングについて考える (JavaScript)

プログラミング

こんにちは。Webエンジニアのkaoruです。

今回はReactの基礎勉強していてちょこちょこ出てくる「イミュータブル」について考えます。

「イミュータブルとは何か?」みたいな記事はあるんですけど、なんとなく納得感がなかったり、なんで要るんだろうっていうことを自分なりにまとめました。

イミュータブルとは?

イミュータブル(immutable)

意味は「不変」です。(逆はミュータブル:変形可能)

変数の値を変えない、ということです。

変数なのに変えないなんて少し妙ですよね。

イミュータブルプログラミング

変数を直接変えない

イミュータブルプログラミングでは、変数の値は直接変えません。

じゃあ、どうするのか?

以下の流れです。

  1. 該当の変数をコピーする
  2. コピーした変数の値を変える(元は変わらない)

サンプルとしては以下です

// 初期値
const current_display = { "color": "red" }

// 一部の値を変更したコピーを作る (上記1,2の手順を同時に行っています)
const copy_display = Object.assign(current_display, {"color": "blue"} )

/* 結果 */
console.log(current_display)  // { "color": "red" }  元は変わらない
console.log(copy_display)     // { "color": "blue" }

直接変えればいいのでは?

なんでこんなやり方するんでしょう?

普通に直接変えれば簡単ですよね。

実は「簡単に変えられる」から問題なのだと思います。

シンプルなプログラムであれば大丈夫かもしれません。

しかし、関数を呼び出した先で関数を呼び出して、その先で関数を呼び出して、、、

どの変数をどこで「簡単に変えて」いるのか、ソースを追いかけていかなければ分からなかったりします。

概要はコメントであったりドキュメントであったり書いてあるかもしれません。

ですが、バグ改修など細かく追う際には深く読む必要があるでしょう。

最近はコンポーネントを組み合わせて作ることが求められる傾向ですし、Reactであれば尚更ですね。

変数の扱い方を限定する

以下のように分けます。

  • 「変更」:計算途中や加工途中の変数に限定
  • 「入れ替える」(再代入):状態管理する変数に限定

さらに、再代入処理の記述場所を限定します。(ルール化)

限定することで値が変わる場所を少なくすることができます。

React Hooks/ Reduxでは、Reducerでしかstateを変えられないようにルール付けしています。(useStateを除く)

—–
余談ですが、const定義は再代入ができないだけで値変更はできます。

何が嬉しいの?

値が変わる場所はReducerの中だけを見ればよく、該当のtypeから処理を明確に追うことができます。

TypeScriptと同じく開発人員が多かったりアプリが大きくなればなるほど効果を発揮するでしょう。

限定分類が理解の肝

個人的にミュータブルの解説で分かりづらいのは、上記の前者と後者の分け方、及び用途が明記されていないからと思います。

「ミュータブルとは何か?」が主題のことが多いので仕方ないのですが、直接変更ではなくコピーして入れ替える、をどう組み込むのか、私はイメージしづらかったです。

ここがしっくりくるまでは「不変といいつつ結局は変えたものを入れ直しているじゃないか」「何故一回コピーしなきゃならないのか。手間なだけではないのか。」など思っていましたね。

まだチーム開発でReactを使ったことがないので実際の効力はわかりませんが、意図は理解できました。

まとめ

  • イミュータブルは変数を直接変えない
  • コピーしてから変えて、再代入することで変える
  • 再代入する処理をコントロールすることで保守性を上げる
  • Reactはエコシステム全体でイミュータブルを取り入れている

では、また〜。

参考

コメント