予言パターン

昨日の続きを発展させて「予言パターン」というアイデアを思いつきました。きっと似たようなことを書いている人がいると思いますが、とりあえず書いてみます。

動機


プログラムとは結局のところ、未来を作り出すものです。その未来は大きくわけて、以下の三つに分類されるでしょう。

  1. 静的な未来
  2. 選択可能な未来
  3. 動的な未来

静的な未来とは、イベントと結果が 1:1 でマップされるものです。迷いがない、決まりきった、退屈な未来です。選択可能な未来とは、イベントと結果が 1:N の関係にあるものです。特定の状況下において、A という結果だったり B という結果だったりしますが、たかだか N 個に限定されます。そして、動的な未来とは、イベントの結果がほぼ無限大であるものです。典型的な「動的な未来」は、人の生活そのものでしょう。


というわけで、AquaSKK では「動的な未来」を扱いません。つまり、「静的な未来」と「選択可能な未来」をどう扱うかがテーマになるのですが、「静的な未来」については状態機械で表現できます。そうなると残る問題は「選択可能な未来」をどう扱うか、ということになります。ここに潜む複雑さをなんとか解消したいのです。

問題


AquaSKK における「選択可能な未来」の一つは、ASCII モードへの遷移を引き起す「l」です。確定状態で「l」が入力されると ASCII モードへと遷移しますが、入力バッファの最後の文字が「z」だった場合には、続く「l」によって遷移ではなく「→」への変換を引き起します。このように、同じ「l」でも、異なる結果が存在するわけです。


この問題を解くには、入力バッファの状態を吟味する必要があります。しかし、入力バッファの中身がむき出しのままであることはなく、通常は、入力バッファを処理する専用のクラス(=コンテキスト)が用意されているわけです。


カプセル化により、周囲からは入力バッファの状態が把握しにくくなります。短絡的な解決策は、ある入力が次にどんな結果をもたらすかを調べるメソッドを追加することでしょう。すなわち、test_fix() だとか、can_transition() のようなものです。こうすれば、周囲から入力バッファの状態を知ることができます。専用のメソッドを使うので、バッファをむき出しでいるよりずっと安全です。


しかし、こうやって安易な方法で「選択可能な未来」をさばいていると、インタフェースはぶくぶく膨れあがってしまいそうです。なによりこの方法はどこかよそよそしく、まわりくどい印象があります。うまく解決する方法はないでしょうか。


入力バッファを処理するクラスは、「選択可能な未来」を判断する能力と条件を備えています。それなら、入力バッファクラスがそのまま「未来」を作り出せばいいのではないでしょうか? 次に進むべき「未来」が「A」であるのか、あるいは「B」であるのか。それを「誰か」に伝えてあげることができれば、その「誰か」は予言された未来を実行し、現実のものへと変換することができます。


入力バッファクラスは、なぜ「未来」をそのまま実行しないのか。それは、入力バッファクラスの役目ではないからです。そして、「イベントの消費者」は「未来の生産者」であり、「未来の消費者」ではない(分離されている)ことが、何か、とても良い構造のような気がしているのです。まだ頭の中だけの世界で、コードでは表現できていないのですが、全てが丸く納まる予感があります。


一方で、クラスが増加する、文脈を読むのが難しくなる、といったデメリットも想定されますね。


ということで、「予言者」が生成した「予言」を「実行者」が「受け取り」、適切なタイミングで「実行」すると幸せになれそうだ、というのが予言パターンのアイデアです。予言の実行によって新たな「予言」が生成される可能性もあります。未来をぐるぐる回すわけですね。まあ実際には「実行すべきタスク」という程度なんですが、こういうのはキャッチフレーズみたいなものですし ;-)


と、ここまで書いてみたところで、冷静になってみると「動的なコマンドパターン」で説明おわりという気もしてきました。ま、いいか。