Flex でビュー(デザイン)とロジックの分離

呼んだ?呼んだよね?
さあ今日はね。 Flex アプリでレイアウトや配色などのデザイン(ビュー)とロジックを分離するやり方を考えてみようよ。

なに?大丈夫だよ。絶対できるって。
じゃあ始めるよ。

すごく簡単なウェブアプリなら「 Flex ってこんなに簡単にできちゃうよー」ってサンプルを紹介するサイトなんかにあるように MXML だけでもできちゃうことがあるけど、ちょっと複雑になってくるとそうはいかないよね。

ってゆうか、そんな「MXML だけで作れちゃうウェブアプリ」のサンプルはエラーハンドリングを実装していない場合がほとんどだしね。
だって Flex を布教するためにはエラーハンドリングみたいな地味で面白くもない技術を紹介してもしょうがないもん。
仕方ないよね。うん。

・・・で、ちょっと複雑になると <mx:Script> タグを使って MXML に実装を書くこともあるけど、規模が大きくなってくると「やっぱりビューとロジックは分けるべきじゃない?」って言い出す人がいるよね。

面倒だけど仕方ないよ。

そんな訳でここらへんでビューとロジックの分離方法についておさらいしておこうね。

やり方はたくさんあると思うけど、今回はよく使われる二つの方法を復習するよ。
いいかい。ちゃんとついてきてよ。

方法1)IMXMLObject を使ったビューとロジックの分離

IMXMLObject は Flex SDK に含まれる Adobe が推奨する方法(?)だね。

パッケージ名を含む完全なクラス名は mx.core.IMXMLObject だよ。
mx.core! なんか大切そうな感じだね。

でも中身はかなりシンプルなんだ。コメントを除くとこれだけだよ↓

1
2
3
4
5
6
7
package mx.core
{
public interface IMXMLObject
{
    function initialized(document:Object, id:String):void;
}
}

これの使い方は簡単。
まずは views/MyCustomComponent.mxml っていうファイルを作って、こんな風に書く↓

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox
    xmlns:mx="http://www.adobe.com/2006/mxml"
    width="400" height="300"
    horizontalAlign="center" verticalAlign="middle">
    <mx:Button id="button" label="ボタン"/>
</mx:VBox>

これはただの白い四角形の中にボタンが置いてあるだけの簡単なカスタムコンポーネントだよ。
これがレイアウトや配色等のデザイン、つまり「ビュー」ってことになるんだ。

で、このボタンをクリックするとメッセージが表示されるようにロジックを実装してみるよ。

そのためにさっき出てきた IMXMLObject を実装したクラスを作る。ここではこれをヘルパーと呼ぶことにしよう。

ファイル名は views/helpers/MyCustomComponentHelper.as という ActionScrtipt ファイルだ。
そこに次のように書く↓

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package views.helpers
{
    import flash.events.MouseEvent;
 
    import mx.controls.Alert;
    import mx.core.IMXMLObject;
    import mx.events.FlexEvent;
 
    import views.MyCustomComponent;
 
    public class MyCustomComponentHelper implements IMXMLObject
    {
        private var view:MyCustomComponent;
 
        public function MyCustomComponentHelper()
        {
        }
 
        public function initialized(document:Object, id:String):void
        {
            view = document as MyCustomComponent;
            view.addEventListener(FlexEvent.CREATION_COMPLETE,
                creationCompleteHandler);
        }
 
        private function creationCompleteHandler(event:FlexEvent):void
        {
            view.button.addEventListener(MouseEvent.CLICK,
                button_clickHandler);
        }
 
        private function button_clickHandler(event:MouseEvent):void
        {
            Alert.show("ボタンがクリックされたよ");
        }
    }
}

急に長くなってきたけど、これだけではまだ動かないから最初に作った MXML ファイルにこのヘルパーを追記するよ。

こんな感じだ。

views/MyCustomComponent.mxml

1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:helpers="views.helpers.*"
    width="400" height="300"
    horizontalAlign="center" verticalAlign="middle">
    <helpers:MyCustomComponentHelper id="helper"/>
    <mx:Button id="button" label="ボタン"/>
</mx:VBox>

4行目と7行目が追加されたヘルパーだ。

これでカスタムコンポーネントが完成した。ビューである MyCustomCompoent.mxml にはロジックは書かれていない。

ここまでのパッケージ構成はこんな感じになる↓

separate-of-view-and-logic-1

あとは、アプリケーションにビューを追加すればOK。

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<mx:Application
    xmlns:mx="http://www.adobe.com/2006/mxml"
    xmlns:views="views.*"
    layout="absolute"
    <views:MyCustomComponent/>
</mx:Application>

これで目的は達成できたね。

だけど、ちょっと待って。ヘルパーの中に「view.addEventListener(ほにゃらら」とか 「view.button.addEventListener(ほにゃらら」ってのが出てきてる。

規模が大きくなってくるとなんだかいちいち「view.」って書くのが面倒だよね。

それに別のクラスからヘルパーのメソッドを呼ぶときには「myCustomComponent.helper.メソッド()」って書かなきゃいけない。
「myCustomComponent.helper.ほにゃらら」ってなにそれ長い!面倒!

そこで最近よく使っているのが次の方法なんだ。

方法2)ロジックでビューを継承しちゃおうよ法(仮称)

これはこの名前の通り、「ビューを規定クラスにして、ロジックをそのサブクラスとして実装する」っていう方法だ。

まずは規定クラスになるビューMXML で作るよ。

views/mxml/MyCustomComponentView.mxml

1
2
3
4
5
6
<?xml version="1.0" encoding="utf-8"?>
<mx:VBox
    xmlns:mx="http://www.adobe.com/2006/mxml"
    width="400" height="300">
    <mx:Button id="button" label="ボタン"/>
</mx:VBox>

これでビューは完成だよ。ヘルパーなんて面倒なものは書かなくていいよ。

次にロジックをビューのサブクラスとして ActionScript ファイルで作るんだ。

views/MyCustomComponent.as

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package views
{
    import flash.events.MouseEvent;
 
    import mx.controls.Alert;
    import mx.events.FlexEvent;
 
    import views.mxml.MyCustomComponentView;
 
    public class MyCustomComponent extends MyCustomComponentView
    {
        public function MyCustomComponent()
        {
            super();
            addEventListener(FlexEvent.CREATION_COMPLETE,
                creationCompleteHandler);
        }
 
        private function creationCompleteHandler(event:FlexEvent):void
        {
            button.addEventListener(MouseEvent.CLICK,
                button_clickHandler);
        }
 
        private function button_clickHandler(event:MouseEvent):void
        {
            Alert.show("ボタンがクリックされたよ");
        }
    }
}

これだけで完成だよ。簡単でしょ?簡単だよね?
あとは MyCustomComponent をアプリケーションに追加すればいいよ。
MXML ファイルのほうじゃなくて ActionScript ファイルのほうだよ。

このパッケージ構成はこんな感じになるよ↓

separate-of-view-and-logic-2

これならロジックを実装したクラスに「view.ほにゃらら」とかつけなくてよくなりかなりすっきり!
しかもビューのなかにヘルパーとか書かなくてもいい!行数も短くなってすっきりすっきり!

そしてこれの一番いいところは MXML の中に <mx:Script> タグでロジックを実装しちゃった昔の Flex アプリも簡単にビューとロジックを分離した構造に修正できるってことなんだ。
つまり、規模が小さいうちは MXML の中にロジックを書いて、規模が大きくなってきたらビューとロジックを分離するっていうやりかたも比較的簡単にできちゃうってこと。

わお、ステキだね!

さあ君もやってみよう。

(オフロスキーって知ってますか?)

One Response to “Flex でビュー(デザイン)とロジックの分離”

  1. mazsi Says:
    3月 5th, 2010 at 17:59

    最近Flex Builder 3を始めた元Windowsアプリプログラマーです。
    なかなか面白いですねー
    参考にしてみます。

Leave a Reply