はじめに
近年徐々に複雑になるwebフロントエンドの状態管理の仕組みとして、ReactやVue.jsといったwebフロントエンドフレームワークのお供にReduxやVuexと言ったライブラリを組み合わせて使うことが多いと思います。
それら二つのライブラリは、Elm
という高品質webフロントエンド構築のための関数型AltJSが用いているThe Elm Architecture
と呼ばれるアーキテクチャに影響を受けて作られました。
追記:
ReduxとElmの時系列はReduxの方が先であり、しかしながら状態のimmutableなどは影響を受けていることから、
現在の形のReduxはElmに影響を受けている所がある。
という表現が正しかったようです。
コメントありがとうございます。
参考
Vuexとは何か?|Vuex
reduxjs / redux
Elm
の型システムや見た目は非常にリーダブルであり、型を読むだけでアーキテクチャの本質に近づけると思いますので、Elmユーザーだけでなく、Redux、Vuexがよくわからないと困っているユーザーの方でも読んでいただけたらと。
リーディング準備
Elmの型システムや見た目が非常にリーダブルと言われたところで、いきなり読み始めて分かるわけがないので馴染みが深いTypeScriptへ変換してElmの型を読む準備をしましょう。
この記事では関数の型を使うことによりアーキテクチャの説明をしますので、関数の型のみ見ていこう!
function increment(x: number): number {
return x + 1;
}
increment : number -> number
increment x = x + 1
上の二つは全く同じ関数を定義していることになります
number型を引数にとってnumber型を返すincrement関数の定義は number -> number
と書くことができる!
引数を二つ以上取る関数の型はこの様に書きます!
function add(x: number, y: number): number {
return x + y;
}
add : number -> number -> number
add x y = x + y
なぜ(number, number) -> number
と書かないのかという疑問が湧くと思いますが、それは物凄い便利な機能と概念がバックに存在します。しかし本題からは外れますので、部分適用
, カリー化
という検索キーワードだけ置いておきます。
簡潔で読みやすい!準備完了!!
そしてこの記事で関数
という言葉は同じ引数が入ってきたときに必ず引数以外の影響を受けずに同じ値を返す、数学的な純粋な関数を指します。
本題
フロントエンドは関数だ
まさにブラウザに映っているビューの状態はただの関数の戻り値でしかないというのがThe Elm Architecture
の考え方であり、実装でもあります。
view : model -> html
model
には実際には任意の型の任意の値が入っており、何かしらの値を引数にとるviewという巨大な関数が任意のhtml
を返すことによってフロントエンドが構築されます。
そして、modelの値が同じであれば常に同じhtml
を構築する関数こそがviewという関数になります。
The Elm Architectureの骨子
どんなElm
プログラムも次の三つの要素に分解することができます。
- Model — アプリケーションの状態
- Update — 状態を更新する方法
- View — HTMLとして状態を閲覧する方法
引用 - https://guide.elm-lang.jp/architecture/
既に登場したViewとModelによって実際にhtmlが構築されているのがわかりました。
しかしユーザーの操作に対して見た目が変わらないwebサイトなんて誰が作りたいでしょうか?
そこで、見た目の為の引数であるmodelの値を変更することにより、表示を変更することができます。
update : message -> model -> model
htmlから発射されたmessageとmodelを引数にして、新たな状態のmodelを返す関数となっています。
全体図
この仕組みにより、モデルを引数にとってHTMLを構築するただの関数がいろいろな状態変化をすることができる様になりました!
実際の型
ここまで若干抽象的な話をしてきましたが、Elmで具体的な一番最小限のアプリケーション定義であるsandbox
の実際の型を見てみましょう。
sandbox :
{ init : model
, view : model -> Html msg
, update : msg -> model -> model
}
-> Program () model msg
init
はブラウザで一番最初に表示した時の初期状態のmodelを定義します。
view
はmodelを引数にとって、Htmlを返す関数です。おまけ付きの様なmsg
はユーザーが弄ったときにmsg型の何かしらをupdateに対して投げるよという意味です。
update
はmsgと現在のmodelの状態を引数にして、新たなmodelを生成して返す関数です。
これらを構造体のフィールドとして定義するとプログラムになるよ!という定義です。
本当にたったこれらのシンプルな3つのことを定義するだけで、全てのことが実現できてしまうアプリケーションが完成してしまうのがThe Elm Architecture
であり、ReduxやVuexがやりたいことの本質なんですね。
まとめ
ReduxやVuexは非常に難しい名前の関数や使い道がよくわからない関数をたくさん定義して、何をしたいのかわからなくなることがありますが、結局やりたいことはmodelを引数にしてhtmlを返す巨大な純粋関数としてwebフロントエンドを定義してあげたいだけなんですね。
view : model -> html
ちなみに、Elmという言語は非常に言語仕様が堅牢でコンパクトであり、不必要な機能を全て廃した非常に学びやすい言語です。
The Elm Architectureも非常にコンパクトで堅牢な為、非常に簡単に高品質なwebフロントエンドを構築することが可能になっていますので、ぜひ皆さんも型を読むだけじゃなくて試してみてくださいね。