こんにちは。まっつんこと松藤です。今回は、実際にユーザ登録アプリケーションを実装する前に、Kahuaの重要な特性であるステートフルについて、Piece_Unityと比較することで理解を深めたいと思います。

MATSUFUJI Hideharu

まず、Piece_Unityのステートフルについて見てみることにします。

Piece_Unityを使ったアプリケーションのプログラムコードは、HTTPによる状態を持たない(ステートレスな)振る舞いの制約を受けません。言い換えると、ユーザの断続的なリクエストが、アプリケーションからみた場合に状態が保持された連続的なものにみえるということです。 Piece_Unityでは、このような状態が保持されていることを前提としたプログラミングが可能になります。より具体的には、アクションクラスのプロパティ値がリクエストをまたがっても保持されていることを前提としたプログラミングが可能になるということです。

HTTPはステートレスなプロトコルであり、それぞれのリクエストは関連を持ちません。そのためユーザ登録アプリケーションのように処理が複数のリクエストにまたがる場合はアプリケーション側で状態を管理する必要があります。通常は、hiddenタグを利用してデータを埋め込んだり、セッションに保存したりといった手段を用いなければらないのですが、Piece_Unityを使ったアプリケーションではフレームワーク側でそれらの処理が行われます。

trunk/basics/web/webapp/actions/RegistrationAction.php
<?php
...
class RegistrationAction extends Piece_Unity_Service_FlowAction
{
    var $_user;
    ...
    function RegistrationAction()
    {
        $this->_user = &new stdClass();
        ...
    }

    function doActivityOnProcessConfirmForm()
    {
        $validation = &$this->_context->getValidation();
        if ($validation->validate('Registration', $this->_user)) {
            return 'DisplayConfirmationFromProcessConfirmForm';
        } else {
            return 'DisplayFormFromProcessConfirmForm';
        }
    }

    function doActivityOnProcessRegister()
    {
        return 'DisplayFinishFromProcessRegister';
    }

    function doActivityOnDisplayForm()
    {
        $flexyElement = &new Piece_Unity_Service_FlexyElement();
        $flexyElement->addForm($this->_flow->getView(), $this->_context->getScriptName());
        $flexyElement->restoreValues('Registration', $this->_user);
        ...
    }

    function doActivityOnDisplayConfirmation()
    {
        $flexyElement = &new Piece_Unity_Service_FlexyElement();
        $flexyElement->addForm($this->_flow->getView(), $this->_context->getScriptName());

        $viewElement = &$this->_context->getViewElement();
        $viewElement->setElementByRef('user', $this->_user);
        ...
    }
    ...

上記のコードは、Piece_Unityを使ったユーザ登録アプリケーション、Piece_Examples_Basicsのアクションクラスのコードです。入力されたユーザのデータは$_userプロパティに格納されますが、それをセッションに保存しているコードが一切ないことがおわかりいただけると思います。

Piece_Unityは、Piece_Flowが提供する継続オブジェクトをセッションに保存することでステートフルな特性を実現しています。PHPでは継続はサポートされていないため、Piece_Flowは有限状態マシンのフレームワークStagehand_FSMを利用して継続サーバを実現しています。(継続サーバについては知りたい方は、Bruce Tate氏の記事「境界を越える: 継続とWeb開発、そしてJavaプログラミング」を参照してください。)

これに対して、Schemeではcall-with-current-continuation (call/cc)という関数を使用した継続がサポートされていますが、Kahuaでは"Continuation Passing Style (CPS)"(継続渡しスタイル)と言われる継続が使用されています。正直、両者の違いまでは追い切れませんでしたorz 面白いネタなので、Gaucheといっしょにお正月に勉強したいと思います。

フレームワークを利用する立場からすると、継続サーバの実装方法よりも使用方法が気になるところです。Kahuaの公式Webサイトにある例を見てみましょう。

もっともっと hello - 継続を使ってみよう
(define-entry (counter)
  (define (viewer count)
    (page "hello kahua! - counter"
          (h1/ "Hello Kahua!")
          (h2/ (format "count is ~a" count))
          (p/
           (a/cont/ (@@/ (cont
                          (lambda () (viewer (+ count 1)))))
                    "inc count") " , "
           (a/cont/ (@@/ (cont
                          (lambda () (viewer (- count 1)))))
                    "dec count")
           )))
  (viewer 0))

この例は、リンクがクリックされるとカウンタの値が加減算されるだけの単純なアプリケーションです。a/cont/は、リンクがクリックされたとき指定した継続を実行することをサーバに登録するためのもので、継続の指定自体は(@@/ (cont proc))で行います。Piece_Unityの場合と同じく、セッションに対する処理が一切行われていないことがわかります。

contという指定が必要な分、Piece_UnityよりもKahuaの方が若干開発者に継続を意識させることになりそうですが、意味を理解したうえでおまじないとして書いてしまえば、大した手間にはならないでしょう。

Webアプリケーションの開発において、ステートフルなコードが書けるということは、より本質的な部分の開発に注力できるということです。我々がWebアプリケーションを開発するときにやりたいことは、セッションに対して読み書きすることではないはずです。ステートフルなWebアプリケーションフレームワークは次世代のメインストリームになる!と思いはじめて約3年が経過しましたが、一向にメインストリームになる兆しはありませんorz

それにしてもKahuaはいろいろな面で興味深いフレームワークです。先ほどの例でも見たようにHTMLの要素までがKahuaのコードとして埋め込まれています。DSLの観点からKahuaを見てみるのもおもしろそうです。

参考文献

トラックバック(0)
  • このブログ記事のトラックバックURL:
コメント