kagamihogeの日記

kagamihogeの日記です。

yui-frameworks の感触とかその辺

yui-frameworks の Beta 版さわってみた - kagamihogeのblog のコメ欄で「データバインディングどうしてる?」を聞かれたのと、その他ちょいちょいいじってみての、yui-frameworks 使った場合の設計・実装に対する所感などについて書く。最初に注意書きしとくと、あくまでも今時点の俺個人の意見なので、アンマリ鵜呑みにしないで下さいw あと、モヤモヤとしたことをグダグダと垂れ流しで書いてます。イメージ段階のコードをダラッと書いてたりと突っ込み所満載な部分多々です。つまり、アンマリ真剣に読まれると困るw

このエントリの知見はどこから来たか

Flex 勉強にライフゲームつくってみた - kagamihogeのblog で作ったライフゲームを yui-frameworks を使って作り直した経験を基にお送りします。実行画面はこんな感じ。ちなみにまだ未完成。こうした方がいいかな? それともこうかな? みたいなことを繰り返す核実験場と化してしまってるので中々先に進まない……


yui-frameworks 使用した場合の設計方針

まず、yui-frameworks 使う場合の設計方針の骨子は既に作者自身が http://akabana.info で書いている。ちょっと長いけど、大事なところだと思うので全文引用。http://akabana.info も、実装の参考として目を通しておきたい。

■V:View in MXML

UIというか見た目ですね。

コンポーネント、ステート、スタイルを使って作ります。

スクリプトタグは、使えません。

主に作業は、デザインが中心で行うようにします。

XXXのビューは、XXXView

■H:Helper in AS3

見た目のお世話をします。

見た目を変更したり、イベント投げたり、データ変換など、ビューロジックを作ります。

Viewに対してひとつ作ります。

主に作業は、デベロッパーがデザイナーと話ながら進めます。

XXXViewのヘルパーは、XXXHelper

■A:Action in AS3

Viewのイベントハンドラの集まりです。

イベントをハンドリングして、ビジネスロジックを作ります。

ステートレスが推奨

主に作業は、デベロッパーが行います。

XXXViewのアクションは、XXXAction

■L:Logic in AS3

同期、非同期のデータロジックを作ります。

非同期のロジックは、ステートフルが推奨

同期のロジックは、ステートレスが推奨

XXXをYYYするロジック

XXXYYYLogic

http://akabana.info より全文引用

ちと抽象的な物の言い方だけど、コレに沿って設計・実装を進めていけばいいんだろうな、と。


yui-frameworks の Beta 版さわってみた - kagamihogeのblog で、俺は「データバインディングどこでやるん?」みたいな話をしていたのだけど。その前にまず、上記引用を読むと、アプリケーションの状態は xxxLogic で持つのが推奨されていることがわかる。ロジックも xxxLogic で持てばいいから、ソレは極自然な発想だと思う。

んで、データバインディングなんだけど…… yui-frameworks だと、Flex に標準で備わってるデータバインディングの機構は使わなくなるかな? と感じている。なんでかっていうと、xxxHelper で view そのものが変数として勝手に設定されるから。つまり yui-frameworks は、xxxView という UI コンポーネントを xxxHelper で view 変数として双方向データバインディングしている、と言えるのではないか、と俺は思う。

public var view:HogehogeView;

コレがあるおかげで、Flex のデータバインディングの仕組みに頼るんではなくて……

public class HogeHelper {
    public var view:HogehogeView;

    public function get hogeValue():int {
        return view.hogeComponent.selectedItem as int;
    }

    public function showResult( message:String ):void{
        view.resultText.text = message;
    }
}

public class LifegameAction {
    public var helper:HogeHelper;

    public var logic:HogeLogic;

    public function hogeButtonClickHandler(event:MouseEvent):void {
        var a:int = helper.hogValue;
        var r:String = logic.goFooMethod(a);
        helper.showResult(r);
    }
}

まぁこんな感じに書けばいいんでねーの? みたいな。

あえてデータバインディングでなく、コードで対応してる理由については以下の通り。

このぐらい短いコードだとワザワザ get 書くのはウザい。が、実際には UI コンポーネントから値をゲッツしてロジック側に渡す前に型変換とか validation とかゴチャゴチャやらにゃならんと思うんだよね。

ロジック終了後に値を表示とかする場合も同様。ロジックのクラスから返って来た値を UI コンポーネント表示用に加工したり、関連してる UI コンポーネントの見た目をいじったりとかゴチャゴチャやらにゃならんと思う。見た目いじりってのは、何かの処理が終わったら一斉に UI コンポーネントの disable を false にする、とか。

なので、イチイチデータ取得するときも表示するときもメソッドを書いている。でも、xxxView からコード追い出せてるし、xxxHelper の view 変数のおかげで実質双方向データバインディングしてるようなもんじゃん? 的な発想から出てきたものです。

まぁ、ASP.NET とか RoR みたいにデータベースのテーブルと直でガッとバインディングは出来ないという不自由さ・不便さはあるんだけどw

だけどまぁ、時と場合によっちゃあ↓みたいな書き方しちゃってもいいかなーとか。

public class HogeAction {
    public function nanikaButtonClickHandler(event:MouseEvent):void {
        helper.view.resultText.value = logic.goFooMethod( 
            helper.view.component1.value,
            helper.view.component2.value,
            helper.view.component3.value);
        }
    }
}

正直、こんな感じな暴挙なコードでもおkかなぁーとも思っている。でも実際には、validation とか UI コンポーネントの見た目切り替えとか(略)と色々処理書く必要あるから、もうちょっと各 VHAL のクラスに責務は分散することになるよね、と。

なので yui-frameworks ぐらいの制約で丁度ええんでねーの? と感じている。

yui-frameworks さわってると「フレームワーク側でユルい制約は用意するよ。後は使用者の好みに合わせてジユウに使ってね」と言われてるような気がするんだよね。Cairngorm はガッチガチにあーしろこーしろと言われてるよーに感じたのとは逆な感じ。

だからといって、別にデータバインディングの価値が減じたわけではない。yui-frameworks がその辺のメンドーなことを肩代わりしてくれてるだけ、って話なだけで。MXML から ActionScript のコード追い出す構造作りこむのって、意外と労力いると思うのよね。



話はトぶんだけど。xxxLogic でステートフルに状態持って、ソレを UI コンポーネントにデータバインディングしたいよ、っていう場合は……

public class HogeAction {
    public var helper:HogeHelper;

    public var logic:HogeLogic;

    public function onApplicationStartHandler( event:FrameworkEvent ):void{
        BindingUtils.bindProperty(logic, "arg1", helper.view.argument1, "text");
}

public class LifegameLogic {
    public var arg1:String;
}

ちょいと乱暴かな? って気もするけど、こんな感じもアリかなぁー、みたいな?

双方向にしたい場合は……

public class HogeAction {
    public var helper:HogeHelper;

    public var logic:HogeLogic;

    public function onApplicationStartHandler( event:FrameworkEvent ):void{
        BindingUtils.bindProperty(logic, "arg1", helper.view.argument1, "text");
        BindingUtils.bindProperty(helper.view.argument1, "text", logic, "arg1");
    }
}

public class LifegameLogic {
    [Bindable]
    public var arg1:String;
}

って書いちゃう。{arg1}ってカタチでは指定できないけど。yui-frameworks では BindingUtils でボンとコード書いちゃえばいいかなぁ、とかも思ったり。あー、まぁ、プロパティを public にしまくったりとかスマートじゃないかなぁー、とは思うけど、まぁ現実こんなもんでいいんじゃね、とも思ったりも。

えー、あー、グダグダで結論出てませんが。今はそんな感じです。サーセン。