2015年11月5日
さらに多くのことが変化する – Fluxは新しい”WndProc”である
(2015-10-13)by Benjamin Pollack
本記事は、原著者の許諾のもとに翻訳・掲載しております。
たまたま今まで知らなかったという方のために言いますと、ReactはWebプログラミングにおける最先端の新技術です。そのアイデアはシンプルです。それは、Reactの各コンポーネントは、JavaScriptにおいて、ビューを冪等(べきとう)に描画します。ビューは、コンポーネントが内部に保持している少量のステートのみに基づいてレンダリングされます。同じステートにすれば、その状態におけるコンポーネントは常に同じようにレンダリングされます。これは、データが変われば、Reactは その変更のみを ブラウザのDOMに適用できるということでもあり、ページ全体の再レンダリングを省略できます。実際、何かを変更するかどうかという決定は 全て 、コンポーネントの内部状態に完全に左右されます。それが、なぜReactが非常に早いのかという根本的な理由です。
しかし実際のところ、React自体には、変更をどのように 伝える かという解決策がありません。そのため、最も一般的な解決策としてFacebookの他のフレームワークであるFluxを使います。Fluxには、データを格納する ストア があります。また、 アクション を処理し、関連するアクションが処理された際にはパーティに適切に通知する ディスパッチャ があります。この一連の流れは間接的に行われます。つまり、ユーザはディスパッチャのアクションのきっかけとなるアクションを起こし、ディスパッチャはストアを更新し、ストアはビューを更新し、それによって、場合によっては再レンダリングが起こる、といった具合です。私の説明よりも、この 的確な図 を見た方が理解しやすいかもしれません。実際のアプリケーションを構築するには、通常、多くのReactのビューとFluxのディスパッチャを全体的に密接に組み合わせ、各部品が互いにうまく機能するように構成します。
上記のアイデアは素晴らしいように思えますが、Fluxを使ったWebサイトのコーディングを見ると、私はいつも感じるのです…何というか、どこか 奇妙 だなと。このパターンを以前見たことがあるような気がするのです。それが全て”新しい”ものであるにもかかわらず、ドラゴン退治の物語 ^(1) のように思えるのです。しかしなぜそのように感じるのかはっきりと指摘することができませんでした。
今までは。
基本原理
ここで、ある思考実験をしてみようと思います。Web用のプログラムではなく、リソースが不足しているグラフィカルコンピューティング環境用のプログラムを書いているとします。恐らく、こうしたよくある埋め込み型のマイクロコントローラは、今ではとても一般的ですが、処理能力がRaspberry Piより劣るものもあります。そのようなフレームワークをどのようにデザインしたらよいでしょうか。
リソースが不足していると言いましたが、そのため、OS Xで行うように各個のウィジェット用にオフスクリーンのバッファを保持するかわりに、必要に応じてのみウィジェットを再描画させるようにします。そうすると、ウィジェットの描いたコードが冪等であるように命令する必要が生じます。さらに(繰り返しますが)リソースが不足しているので、実行時間等をいたずらに大きくしたくありません。全てをシンプルにしておくために、各ウィジェットを1つのプロシージャに関連付けて、そのプロシージャに2つの引数を与えます。たった今、ユーザがどのようなアクションを起こしたのかを表す整数値と、(もし適用できれば)付加的な、アクション固有のデータのポインタです。そうすれば、各ウィジェットは可能な限り最も効果的な方法で各メッセージを扱うことができます。最後に、ユーザのアクションがウィジェットの再描画を要求するかもしれないので、変更が必要になったら、ウィジェットが私たちに通知できるようにします。描画は冪等なので、再描画しなければならないものが何であれ、再描画するだけでCPUの使用量を最小限にできます。最後に、プログラマの心の平穏のために、これらのウィジェットをネスト可能にし、互いにカスタムメッセージを送れるようにします。
やりましたね! これでWindowsのデザインが完成しました。
具体的に言うと、1985年のWindows 1.0です。
過去からの一撃
これは掛け値なしに本当のことですが、上で説明した方法が、少なくとも、Windows7までのWindowsをプログラムしていた、まさにそのやり方なのです。さらに言うと、最近のWindowsプログラムの多くは内部的に、今もこの方法で機能しています ^(2) 。 WM_PAINT
メッセージを通して要求を受けると、ビューが描画されます。処理を早くするため、 WM_PAINT
メッセージは通常ビューの中でローカルにストアされるステートだけを使い ^(3) 、繰り返せるようにしておきますが、ステートの操作は禁止されています。描画はステートの変更とは分けられているので、Windowsは実際に再描画が必要なスクリーンの一部分しか再描画できません。各ビューはそれぞれ関連付いた WndProc
と呼ばれる関数を持っており ^(4) 、4つのパラメータがあります。実際のビューが更新される時、 uMsg
は、整数で表されるのメッセージ型です。 uMsg
と lParam
という2つのパラメータは、メッセージ固有のデータを格納しています ^(5) 。 WndProc
はメッセージにレスポンスする際に(多くの場合、追加的なアプリケーション固有のメッセージを送ることにより)どんなデータストアも更新します。次に、もし適用できれば、データストアはスクリーンの関連部分を無効なものとしてマークすることができ、新たな描画サイクルを引き起こします。最後に、プログラマの心の平穏のために必要なことですが、多くのビューを、他のビューの内部と組み合わせることができます。仮想上は、Windowsで見られるどのウィジェット(あらゆるリスト、チェックボックス、ボタン、メニュー)もそれぞれが、実際には小さな WndProc
とメッセージを持った小さな再利用可能なビューです。
これはまさにFluxが行っていることです。Fluxの公式レポジトリのサンプルアプリケーションを見ると、このデザインがはっきりと分かります。これまで旧Windowsのプログラミングで行ってきたような、 enumとして定義されているメッセージ 6 が確認できます。 全てのメッセージに対する大きなスイッチ宣言 が見られますし、メッセージの actionType
に基づいて異なるデータが抽出されていることに気づきます。そしてもちろん、少量の内部状態に基づいて 冪等にレンダリング するコンポーネントも確認できます。
全ての古いものは再び、新しいものとなるのです。
大騒動の後に
Fluxが 有効 であるのは明らかです。それだけではありません。明らかに スケール します。Facebookが代表的なものですが、プログラマや企業はこのスタイルで巨大で機能的なアプリケーションを書いています。
しかし、それは驚くに値しません。結局、多くの企業が、古いバージョンのWindowsでも同様に、巨大で機能的なアプリケーションを書きました。Fluxが 有効 で、有効なだけではなくさらに 以前のものよりも優れている からといって、それがWeb開発の最終的な形であるとは言えません。
Windowsが WndProc
に由来するコードにずっと縛り付けられていたわけではないように、Web開発の進歩がここで止まることはないと信じています。私たちはInterface Builderと Morphicを再発見するでしょう。VisualAgeや Delphi、そしてVisualBasicに関して新たなWebベースの考え方を持つようになるでしょう。その内部でFluxが息づいていたとしても、そうしたことについて、日単位で考える必要はありません。そうしたことは、いずれ起きると分かっています。これまで何度となく、多くのプラットフォームで起きたことだからです。歴史的に見ると、多くの前例があります。ただ、待てばよいのです。
ただし、今、過去を振り返ってみることの利点があるとすれば何でしょうか。それは、単に1980年代半ばの手法をWeb開発にあてはめただけに過ぎないと認識することによって、私たちは、前回よりも少しだけ早くこのフェーズを乗り越えられるだろう、ということです。
そうなることを期待しています。
-
もしくはデーモンです。 ↩
-
WinUIプログラムはあるレベルにおいては、恐らく実際にはこのように機能するでしょう。しかしWinUI用の抽象化の最低レベルはありがたいことにもっと高いのです。 ↩
-
興味がある方のためにお伝えすると、
GWLP_USERDATA
を通してです。 ↩ -
WndProc
と呼ばれる理由は、WindowsがViews windowsを呼び出すからです。実際、Windowsにおける”Window”のコンセプトは、WindProcが管理する小さなスクリーンの塊に過ぎません。Cocoaが明らかに、抽象化のかなり高次なレベルを顕在化させているのに対して、実際にOS XのQuartzは同様の呼び出しを深部で行っていました。 ↩ -
実際には、最も単純なメッセージでは
wParam
は無視され、lParam
はメッセージ固有のデータを格納するstruct
をポイントしました。このことは、Fluxのモデルに近いことをより一層よく示すと言えます。 ↩ -
もしくはそれらのJavaScriptバージョンです。 ↩
株式会社リクルート プロダクト統括本部 プロダクト開発統括室 グループマネジャー 株式会社ニジボックス デベロップメント室 室長 Node.js 日本ユーザーグループ代表
- Twitter: @yosuke_furukawa
- Github: yosuke-furukawa