読者です 読者をやめる 読者になる 読者になる

Garrett 先生に先日の N3 質問を直接ぶつけました

あとで読み返してみたらあまりにも言ってることが意味不明なので後で直します。orz


 CakePHP カンファレンス懇親会で、来日中の CakePHP 開発マネージャ Garrett J. Woodworth 氏に先日の質問を直接ぶつけるという貴重な機会を得ました。写真は Garrett の席に乱入する前にあらかじめ用意しておいた即興質問状とその場で書きこまれていった図や回答などの様子です。

 結果から申し上げれば、自分が結論づけた「モデルはデータベース特有のやりとりをモデル化している」とかこれとかは考えすぎでした。

 僕の疑問点は、

  • コレクションとエンティティに分かれた O/R マッパーは、通常のプログラムのやり方の延長線上で理解可能
  • しかし CakePHPAkelos のモデルは「1レコード」と「1テーブル」のどちらをモデル化しているのかよく分からない


 という点です。 CakePHP カンファレンスの懇親会で Garrett の席に突撃し、ナインティナインナイツの画面:

 を見せて、 Garrett とゴブリンをモデルに話を始めました。Garrett がゲーマーで良かったです。

 実は、以前のエントリにはひとつミスがありまして、どう考えてもゴブリンと師団の両方をモデル化しなければならない題材を書いてしまいましたが、今回の質問では早々に話を、

「GoblinController で $this->Model は単体のゴブリン1匹を指しているのか、ゴブリンテーブルを指しているのか?」

 というテーマにちゃんと絞りました。

 結論からいうと、 "気持ち的には、1匹を指している。しかしゴブリンテーブルを操作することもできてしまう" ということです。

 前回より少しミッションがシンプルになっていますが、「指定した値よりHPが低いゴブリンのAIステートフラグを撤退に書き替える」という処理を、かんたんに次のように表現するとします:

 GoblinListItr itr;
 for (CGoblin *pGoblin = pGoblinContainer->getWoundedFirst( &itr, 20 );
      !pGoblin; pGoblin = pGoblinContainer->getWoundedNext( &itr );
 {
     pGoblin->flag = ESCAPE;
    // pGoblinContainer->sync( pGoblin );
 }

 コンテナから書き替える対象となるデータのアドレスのリストを取得して、メモリ上の値を直接変更しています。これを Web MVC のモデルに落とし込んだ場合、僕はてっきり、

<?
  pGoblinContainer->setEscapeFlagToWounded( 20 ); // Life <= 20
?>

 と書けるようにしておくことが推奨されるのだと思っていました。これを理解するために、特別高速な転送モード/操作モードを持つ補助プロセッサー(ないしは補助装置)とのやりとり……と脳内で置き換えれば、なんとか感覚的に食らいついていけるなどと訳の分からない妄想を繰り広げていたところです。

 が、 Garrett には、ひとつ前の例のように、群から対象となる個体のリストを取得して、そのリストをモデルの更新メソッドに渡す手順をアピールされました。これなら非常に分かりやすい話ですが、難しく考えていた(そして O/R マッパーとは大きく違うと考えていた)自分にとって、これはどういうことなのだろうとも思いました。

 この席で聞いた話なのですが、 CakePHP のデータモデルは、デスティネーションオペランドとなるアクティブレコードを経ずに "Goblins" の複数行を直接更新するといったやや SQL 的な操作メソッド(updateAll や deleteAll)をもともと持っていなかったそうです。しかし、 DBMS は UPDATE ... SET ... WHERE ... の形に落とし込むことで対象の検索と書き換えを同時に行うという操作が可能ですから、データベース側へのそういうクエリーに直接繋がるような機能拡張がオーダーされた。そしてバージョンアップの過程でそれが採用されたという経緯らしいのです。

 これは Garrett に確認したわけではないので、もともとあった予定に沿った機能拡張だった可能性も拭えません。が、すべてが理想から設計されたわけではなく、ある程度現実問題と付き合って今の形に落ち着いていった(かも)という経緯は重要でした。むしろ DBMS 固有の(有利な)サポートのことは忘れて、根底的には Entity と Container に分かれていて、 Controller には Container が "Model" という表現で put される……というステップのことだけを考えれば、いつものコンテナやシーングラフ等と話は変わりません。これなら Web IT エンジニアでなくても十分に操作方法を把握できます。

 こんな門外漢のトンチンカンな質問に付き合ってくれて、 Garrett 、本当にありがとうございます! また、疑問を共有し一緒に Garrett と話し合い、通訳もしてくださった CakePHP コミュニティの皆様、ありがとうございました。 m(__)m