副作用について個人的に整理してみる(2022年版)
個人的にではありますが、プログラミングにおける副作用の考え方について、以前よりは認知度が高くなってる気がします。私も副作用は極力起こさないよう意識はしているのですが、そもそも副作用ってどんなもので、どう対応すべきかというのが少し自分の中でフワッとしてるような感じがしました。
ということで、今回は副作用について現時点(2022年)における、まとめ的なのを書いてみます。
<副作用とは何か>
まず副作用の定義的なところについて、下記の記事にまとめられてます。もちろん、人によっては言葉の選び方とか異なると思いますが、個人的には「状態(値)が変わりうるもの」というのがしっくりくる感じがしました。
例えばフロントエンドでいくと、以下の記事にあるような、State・Cookie・Historyなどが、この副作用に該当するものとして挙げられています。
状態が変わると、処理に対して一定の結果が返ってこないこともあります。今現在どういう状態で、どのような結果があるべきなのか推論しにくいというのが、副作用のデメリットかなと思います。
<対応のアプローチ>
副作用はあまり良くない印象はありますが、とは言え状態が変わりえないシステムは、あまり存在しないと思います。そのため、まずはいかに副作用を認識できるようにするかが、大事かなと考えています。
以下の記事では処理をコマンドとクエリに分けて、整理されています。コマンドは副作用が発生する処理、クエリは副作用が発生せずパラメータを受け取って結果を返す処理になります。
例えば処理の中で、コマンドとクエリが混在していると、どういう結果があるべきなのか分からなくなるといったことが発生しうるので、なるべく分離した方が良いというのがアプローチになります。
<CQRSについて>
コマンドとクエリということで出てくるのが、CQRS(コマンド・クエリ責務分離)の考え方です。CQRSについては、下記の記事にざっくり概要が説明されているのですが、クエリとコマンドの処理を分けて、なおかつDBも各処理で分けるというものになります。
とは言え、これは原則論であると思っていて、実際にはコマンド・クエリを完璧に分離するというのは厳しいということもあるだろうし、DBを2つ用意して同期させるのはコストがかかるということもあるでしょう。下記の記事にある通り、まずは部分的導入から始めるというのが現実的なところだと思います。どこまで分離すれば良い落とし所になるかはそれこそ現場によって変わるとは個人的には思います。
ただ、部分的導入であっても効果はあると思っていて、今までコマンド・クエリが意識されていない現場であれば、副作用を意識するきっかけになるだろうし、一度そういった仕組みを作れば機能追加をする時も乗っかりやすいという面はあると考えています。
Discussion
関数型プログラムは副作用がないといわれていますが、違います。キャッシュによる高速化の違いは、関数型でも発生します。リモートにあるファイルをキャッシュする場合に、リモートのレイテンシーが 200msec でも、ローカルのしかもCPUキャッシュで作業できるなら、速度は、理論的には100万倍ぐらい違います。現実的にみつもっても、1000倍ぐらいの差は簡単にでます。
というわけで面白い領域があります。特にビッグデータで顕著です。
電波記事あげているのでぜひ見てください。
日経記事を検索する日経テレコンは、多くの公共図書館でつかえますから、ぜひ使ってみてください。