2010年5月30日日曜日

GWTについて

GWTについて 


概要
    GoogleWebToolkit
    Googleが作成/配布している、Javaで書いたプログラムをJavaScriptに変換するツール。
    GAEがJavaで記述できるため、クライアントサイドをGWT-Javaで、サーバサイドをGAE-Javaで書く、といった事ができる。
    クライアントもサーバも、Javaで横断して開発できるぞ!

    、、、と言いたい所だけれど、Java-JavaScriptへの変換には、制約がある。
    まとめ中。

    また、Javaのプログラム中から、任意のJavaScriptを実行する事ができる。
    過去のライブラリとか使える。



DIFrameworkとの連携
    GINというモジュールを使用する。Guiceの兄弟。
    GINについては別記事参照
    
    Google GIN


HTML5に関わる事
    Canvas要素との連携
        GWTからCanvasを使うには、今のところincubatorモジュールを組み込む必要がある。
        
        類似で、GWT-NSという個人実装のモジュールがHTML5の実装予測機能を実装していて面白い。
        製作中の実装の機能毎切り分けがうまくできれば、楽しいだろう。
        次第にGWT自体が追いついているので、楽しみ。

    
制約
    まとめ中。
    ああーこんなことはできないのか、など。大まかにはGoogleが作成していないJava-JavaScript機能は使えない。
    
    Javaでのリフレクション
        無理。



Imageの描画について
    GWTのイメージには2種類のオブジェクトを使用したものがある。
    WidgetとしてのImage    
    Widget:GWTCanvasの描画対象としてのImageElement 
    
    ImageはWidgetとしてそのまま他のWidgetと同じように扱える。
    GWTCanvasを使う方のImageElementの扱いは、HTML5のCanvasタグでの描画になる。

    おまけ:
    WidgetのImageを拡張したFitImageという型を出力、コーディネートするImageLoaderというライブラリがGoogleCodeにある。
    
    ImageLoader

    使えるが、どうせならWidgetすべてのOnloadが読める機構の方が欲しい。
    全コンポーネントが準備可能になるまで待ってられない、なんて状況も今後はあり得てくる。
    
 



この記事へのリンク
公開完了 -toru inoue 10/05/30 16:14 



Mercurialについて

Mercurialについて 




概要
    分散バージョン管理ツール
    コマンドラインで稼働するツール。
    このツールと、連動する形でWindowsやMac向けにちょこっとGUI付きのクライアントソフトがある。
    前提として、ツールをインストールした後、GUIをインストール、先にインストしておいたツールを指定して
    GUIから使う、という形になる。

    ぶっちゃけCUIでの操作はミスの元なのでGUI付きクライアントを使おう。
    オススメのGUIがあったら教えてほしい!
    →    sassembla@hotmail.com
    
    (写真はmurky/Mac)



インストール



クライアントアプリケーション
    Mac版:
        murky

        →Get Murky!
            と書いてある下のリンクから最新版を取得、Macであれば解凍するとアプリケーションが出てくる。    
            起動時には画面のようなウインドウは出ないので注意。リポジトリを選んだ場合に画面は表示される。
            
            使い勝手
                    まだよくわからない。GitXとインターフェース的に似ている。


    Windows版:
        TortoiseHG



使用用途
    バージョン管理に使用する。

    プロジェクトごとの管理の他に、配布目的でSVNのTrunkやGit,Mercurialのリポジトリが公開される事がある。
    用途は、「ここから落とすと最新バージョンの共有ができますぜ」なのだが、
    これらの機能や使い方について、ほぼ日本語での紹介を見た事が無い。
    
    最近ではソフトウェアのダウンロードサイトでも使われてきていて、そういうのが全く発生しない日本に
    ちょいと心配が募る。



落とし方
    主にコマンドラインから、
    hg clone https://XXXXX
    
    入力すると、Currentなディレクトリにダウンロードされる。

    svnとhg,gitで若干所作が違うので、一概に同じ現象が起こる訳ではないが。




このページへのリンク
公開完了 -toru inoue 10/05/30 16:13 



環境構築:Java

環境構築:Java 



概要:
    JavaSE/JavaEEの開発環境を用意するために、必要なもの、処理をリストアップ


使用ツール:
    Eclipse   
        Eclipse Foundationのアプリケーション。
        オープンソースで開発が進められているIDE(統合開発環境)
        Javaのソース記述/ビルド/デプロイが簡単に行える。
        基本機能の他に、pluginの形で様々な機能が存在する。


環境:
    Mac/Win
    JRE5.0相当
    JDK5.0相当


インストール:
    1.サイトからダウンロード
        ダウンロードセンターがある。
        

    2.置きたい場所に置く
        DLしたフォルダが圧縮フォルダならば解凍し、解凍されたフォルダをどこか好きな所に置く。
        それで完了。

    
    3.日本語化
        (英語がちょっとでも読めるならオススメしません。)


    4.ワークベンチの設定
        Eclipseでは、プロジェクトやプログラムが置いてあり、ビルド等行うファイル/フォルダを、
        ワークベンチ(作業場所)という概念で複数登録できます。

        Eclipseが工作マシンで、ワークベンチは工作台、
        各プロジェクトは工作台の上に転がっている素材、というイメージです。

        一つのEclipseから複数の工作台をまたに掛けて制作を行う事ができますし、
        制作する素材ごとにEclipseをわけてインストール、使用するなんて事も可能です。
        

        気をつけるべきなのは、Eclipse自身が工作マシンなので、plugin入れたりアップデートを
        掛けたりでEclipse自体の性能が変化してしまう事。

        しばらくBというワークベンチで作業をしていて、一度離れて、plugin入れて、、
        久しぶりにBというワークベンチに帰ってきたらビルドエラーが! なんてこともあり得ます。

        
 pluginのインストール
    a.プラグインが置かれているサイトに行き、
        "このアドレスにpluginが置いてある"という内容の記述を探そう。

        Eclipse plugin XXXX などとGoogleなどで検索して、欲しい機能を見つけましょ。
        Eclipseと書いてあればたいがいサイト上でpluginを提供してくれている。
        Ex:
            下のサイト内の、
            http://relo.csail.mit.edu/registered.php
                
                ↓こんな項目。
                Download Instructions
                
                近所をみたら、Update URL: http://relo.csail.mit.edu/update とか
                書いてあるとおもいます。 このアドレスを覚えておきましょう。


    b.Eclipse上で、Help>Install New Software... を選択。

    c.Add... ボタンをクリックし、サイト名(自由に入力OK)とサイトURL
        (aで見つけたもの)を入力しよう。
            
        ここでのサイト名は、後で自分がわかりやすいように、というメモの意味合いが強い。

    d.Acceptを求められたり、Nextを押したりしてインストール
        問題が発生、インストールに失敗する事が有る。

        多くの場合、競合するpluginがあったり、pluginどうしで扱う機能のバージョンが
        異なったりする。
        →そうなったらクリーンインストールした方が楽です。
        もしくは、割と親切にエラーを出力してくれるので、
        エラーとにらめっこして経験を積むのもいいかも。


        Eclipseのバージョン、
        pluginが使用(依存)する他のpluginパーツのバージョンの差によって、
        使えたり使えなかったりすることがあります。
            

        

おすすめplugin 追加 -10/03/31 1:13 
    Relo
        Javaソースを任意の部分だけソースからUML図式化する補助ツール。
        
        http://docs.google.com/View?id=dwp4j2r_222cpx6q7ch


以上。

このページのURL
公開完了 -toru inoue 10/05/30 16:11 





UMLツール Reloについて

UMLツール Reloについて



概要

    MITライセンスのEclipseプラグイン。

    JavaのクラスをUML化できる。


    特徴としては、「自分がUML表に出したいオブジェクトを自由に選び表化できる」。


    サイト:http://relo.csail.mit.edu/



注意点

    2007年時点でサポートが終了している。 現在、より高度な機能を持ったバージョンがarchitexa社で開発中とのこと。

    最新情報→http://www.architexa.com/


    完成したら乗り換えた方が良いと思われる。


    



インストール
    EclipseのHelp→Install new feature で、下記アドレスを追加、インストールを実行する。

http://relo.csail.mit.edu/update



    JDOに関連するプラグインが既に入っていると、インストール時に破綻するようだ。


    Eclipse3.5.2を使ってのクリーンインストールだと巧く行った、


    ファイル>保存する事で後から参照できた。

    エラーが山ほど出ているのが気にはなる。。。




使い方

     1.図を作る
        Eclipseのパッケージエクスプローラーウインドウ内で、UML化表示クラスを選択、右クリックでRelo系のコマンドを選ぶ。
        .javaファイル>右クリック>Open in Relo Session 


    2.図にクラス情報を追加
       XXXX.javaファイル中のインスタンス、参照、メソッドがリストとして出てくるので、任意に選択、表示

    


    3.参照先、参照元を図に追加

        メソッドやクラスにマウスを持っていくと、→(やじるし)が表示される。

        表示したメソッドから参照先、参照元を確認する事ができ、呼び出されるインスタンスやメソッドからオブジェクトが表化される




保存
    作成したファイルは、Fileメニューから保存する事ができる。



補足
    既存のクラスからUML図を作り出すツールなので、従来の設計とは異なる。
    ラピッドにやるならば、先ずUML図を書いておく必要がある。
    なんだろうな、説明用とか、後追いでコード関係を清算する時に使えるかな。

        
    
このページへのリンク
公開完了 -toru inoue 10/05/30 16:11 



GWTDesignerについて

GWTDesignerについて 



概要
    Instantiations, Inc.製のWebページデザイン用のEclipseプラグイン。
    GUIでのGWTのWidgetレイアウト機能がある。 
    イベント生成機能がある。
    エミュレート機能がある。

    =素晴らしい。

    、、、ちょっと重い。これは環境が非力なのもあるけど。


インストール
    まとめ中    
    

購入のとき
    Eclipseのプラグインが言う通りにログを送ったりしたのだけれど、
    中の方とメールでやり取り、結局サイトから購入した。

    オートメーションだと思い酷いメールを送ってしまった。。

公開完了 -toru inoue 10/05/30 16:09 

Guiceについて

Guiceについて 


概要
    Googleが使っているDIに特化したJavaフレームワーク(というか機能)
    フレームワークの定義が”To Do Here” ここでこんなことをしろ に限定されている物の場合、当てはまりません。

    サンプルを一つ作ってみます。
    今回作成するサンプルは、
    1.Guiceで「インターフェース HelloService」とそのインターフェースを実装した「クラス HelloServiceImpl」を関連づけ
    2.Guice経由で、 HelloService インターフェースの何らかの実装を使うクラス MyObject のインスタンスを作成
    
    MyObjectクラス内のHelloService インターフェースに、HelloServiceImplクラスのインスタンスが組み込まれていることを確認します
    
    ? 何がおこるん?

    通常なら、HelloServiceImplクラスをインスタンス化させて、
    MyObjectのコンストラクタに入れてMyObjectをインスタンス化、でいいんですが、
    ここでは、HelloServiceImpl、HelloService、MyObjectについての一切のnew演算子を使いません。    

    Guiceがそのへんの肩代わりをやってくれます。
    The new "new" (あたらしいNew) が見れます。
    
    

バージョン
    今回は2.0を使用


使用するための準備
    1.ダウンロード
        下記からguice-2.0.zipとかを持ってくる。

        zip中には、下記が入っているはず。
            COPYING.txt
            aopalliance.jar
            guice-2.0.jar
            guice-assistedinject-2.0.jar
            guice-jmx-2.0.jar
            guice-jndi-2.0.jar
            guice-multibindings-2.0.jar
            guice-servlet-2.0.jar
            guice-spring-2.0.jar
            guice-struts2-plugin-2.0.jar
            guice-throwingproviders-2.0.jar
            javadoc(フォルダ)


    2.Guice関連のJarをビルドパスに入れる
        今回のサンプルでは下記だけを使う。

            guice-2.0.jar
            aopalliance.jar

環境
     今回はクライアントサイド、ただのJavaApplicationとします。
    サーバサイドでは動かない、完全にローカルのJavaで動くもの。
    Java5以上。
    


サンプルのコーディング
    HelloServiceという、とりあえずHelloWorld的な事をするものをサンプルで作ってみる。
    


Main.java

import com.google.inject.AbstractModule;

import com.google.inject.Guice;

import com.google.inject.Injector;

import com.google.inject.Scopes;


/**

 * エントリーポイントのクラス

 * @author sassembla

 */

public class Main {

    /**

    * main関数

    * @param args

    */

    public static void main(String[] args) {


        //インスタントにInjection処理を記述 AbstractModuleを拡張した別のクラスに書いてもいい。ここでは記述量の問題で逃がしてください。

        Injector injector = Guice.createInjector(new AbstractModule(){

            @Override

            protected void configure() {

                bind(HelloService.class).to(HelloServiceImpl.class).in(Scopes.NO_SCOPE);//スコープ指定で組み込むことができる。これが鬼機能。

            }

        });


        MyObject object = injector.getInstance(MyObject.class);//実行したいオブジェクトにヒョウイさせる

        object.execute();//処理を実行

    }


}




HelloService.java

/**

 * サービス定義のインターフェース

 * 定義インターフェースでは、外部向けの内容をインターフェースとしてまとめておく事で、

 * 見せたくない実装を隠せる。

 * @author sassembla

 *

 */

public interface HelloService {

    /**

     * 名前のみ

     */

    public void sayHello();

}




HelloServiceImpl.java

/**

 * 実装

 * 

 * 抽象物ではなく、実際の処理が行われる部分

 * @author sassembla

 *

 */

public class HelloServiceImpl implements HelloService {

    int count = 0;

    /**

     * とりあえずなにかしら実装

     */

    public void sayHello() {

        System.out.println("Hello, guice!_"+count);

        count++;

    }

}




MyObject.java

import com.google.inject.Inject;

/**

 * 使用したいクラスをヒョウイさせる対象

 * 

 * @author sassembla

 *

 */

public class MyObject {

    private HelloService helloService = null;

    

    @Inject

    public void setHelloService(HelloService helloService) {

        this.helloService = helloService;

    }

    

    public void execute() {

        helloService.sayHello();

    }

}





実行結果
    プリント文出力:Hello, Guice!_0
    動いてる。ナイス。

    実際に動いているという事は、
    MyObjectクラス内のHelloServiceクラスに、HelloServiceImplクラスのインスタンスが組み込まれている
    ということっすね。

    なんで? MyObjectの setHelloService メソッドはどこからも呼ばれて無いじゃん。
    その辺を、
    MyObjectクラスのsetHelloServiceメソッドについてる@Inject アノテーションによってGuiceが「察してくれた」形になってます。 


    Reloで出力してみました。
    
    interface以外関連性無い。

    白矢印はInterface、黒矢印は呼び出し(=メモリーに展開された、ということ)

    InterfaceのHelloServiceと、それを実装(Implements)しているhelloServiceImplとの間の関連はありますが、HelloServiceImplの
    クラス化は見た目行われていません。


利点
    GuiceがhelloServiceImplのインスタンス化や保持を「しれっと」やってくれています。
    ☆Guice(Injector)がインスタンスの作成、保持をしている
        new演算子は、AbstractModule記述以外に全く使用されていません。Guice/Injectorがすべてのインスタンスを保持してくれています。
        
    
    モジュール側(今回はMainがあるクラス)から見ると、HelloService と HelloServiceImplが結びつけられています。
    ☆HelloService さえ実装されてれば、 HelloServiceImpl 以外のクラスでもMyObjectから使える!
    インターフェースを用意して、バインド対象を入れ替えれば、使う側からの区別が消えます。

    ☆コード上に依存関係を記述できる!
        プログラム外の設定コードとさよならできます。 主にクォーテーション、目コピー&手ペーストとさよならです。
     

スコープについて
    bindの際にスコープという要素の設定が出来ます。定義されるのは、bindしたクラスのライフサイクルです。

    Main.javaの中で、下記のような行があります。
    bind(HelloService.class).to(HelloServiceImpl.class).in(Scopes.NO_SCOPE);//スコープ指定で組み込むことができる。これが鬼機能。

    スコープは、Singleton やら Transactionalやら、いろいろ魅力的なものがそろってます。
    NO_SCOPEだと、特に何のフォローもしません。デフォルトはNO_SCOPEです。

    SINGLETONだと、Injectorの寿命が或る限り、あたかもbindしたクラスがシングルトンであるかのように、
    Injector から取得できるクラスが固定されます。
    試しに、スコープをSingletonに変え、Main.java に下記のコードを加えてみると、結果が面白い事になります。

    /~/
    bind(HelloService.class).to(HelloServiceImpl.class).in(Scopes.SINGLETON);//スコープをシングルトンに変更
    /~/
    MyObject object = injector.getInstance(MyObject.class);//実行したいオブジェクトにヒョウイさせる

    object.execute();//処理を実行

    

    //追記

    MyObject object2 = injector.getInstance(MyObject.class);//実行したいオブジェクトにヒョウイさせる

    object2.execute();//こんどはobject2でexecuteしてみよう


    

    結果:

    プリント文出力:Hello, Guice!_0
                         Hello, Guice!_1
                        

    sayHelloが一つのHelloServiceImplから行われた事になっています。
    GuiceがSingletonとしてHelloServiceImplの実装を持ってくれている。
    
    SINGLETONに変えた事により明らかになるのは、
    NO_SCOPE/デフォルトだと、通常のインスタンス作成と変わらない内容だ、という事です。(試しにスコープを戻してみるといい)
    これ、Guiceを通したnewの定義。

    スコープによって、bindしたインスタンスの寿命を設定できます。
    すごく簡単に乱暴に無知に書くと、インスタントに作って使い捨てたければNO_SCOPEで、何度も使いたければSINGLETONで。

    これ以外にも大量に、スコープに関する機能があります。Sessionとか、Transactionとか。 
    それぞれ、どんな寿命をbindしたオブジェクトに与えるのか、なんとなく想像がつくかと思います。
    特にサーバ周りが強烈便利すぎる。

    他人が作った物を使う際に非常に使えます。物理エンジンとか、描画スクリーンとか、
    ステートマシン的なものを使う際には効果絶大です。
    使いたい機能のインターフェースさえ作ってかぶせれば、OKと。 はじめからインターフェースがあればなおさらです。
    

スコープがもたらす副産物
    BoilerCode(湯沸かしコード、とか?)と総称される、シングルトンとして呼びだされてほしいクラスを作るときに
    毎回のように書かなければいけないコードは、書く必要から不要です。 
    書かないでよろしい。 すげー。 
    もうコンストラクタをprivateにしなくていい。
    
    フレームワークとしては初めて、
    ”外見上でなにもしていないように見えてコード記述を管理している機構”なのでは。

    シングルトンか否かは、使う側が設定していい。
    とても素敵。

    ただ、シングルトンを巡る問題は、シングルトンのコードの存在とは別の次元なので、あしからず。


感想
    既存のものと並べてフレームワークと呼ぶ、というよりは、
    インスタンスの依存、保持、ライフサイクルをサポートする機構/機能 です。
    
    アノテーションでの記述は、楽の一言に尽きる。
    これだけ簡単に使えるという事は、他人が書いた物を使う上でも、使用上の制約を低く保てる、という事。
    他人の作った物をどれだけローリスクで限定範囲で使えるか、という部分と、
    また他人が使えるように自分も細分化して物を作れるか、という事の補助になります。

    複数のインスタンスから共通のステートマシンにアクセスする場合などがあるとしたら、
    それはトランザクションがなんとかするのか。

    驚くべきは、GWTでも使える(GIN)、Androidでばっちり動く(Without AOP版)、とかその辺。マジかYO。マジでした。
    今後書き足します。



追記
    GWTとの連携

    Androidとの連携
        without aopであれば使える。
        
    Doja/Starとの連携,,,天変地異とか奇跡が起こったら書くかも。まあ今後、もう出番なさそうだし。
    


このページへのリンク
公開完了 -toru inoue 10/05/30 16:08 









GINについて

GINについて


概要
    GWTで使用する用途のGuice
    を連携させる


ダウンロード
    Guice用の環境、GWT用の環境はおのおののページを見るとして、
    連携にGINというプログラムが必要になる
    
    ダウンロード
            gin-1.0.zip


使用法
    1.DLしたファイルの中から、GIN.jarをビルドパスに含める

    2.インポートに下記を加え、モジュールクラスを作成
    import com.google.gwt.inject.client.AbstractGinModule;
    
    3.GWTのgwt.xmlに、
    <inherits name="com.google.gwt.inject.Inject" />
        を追記
    

    あとは、通常のGuiceを使ったプログラムと合一できるはず。

   
Guiceとの差
    Injectorの代わりにGinjector 
    Ginjector.getinstance()メソッドはありません。
    


このページのURL
公開完了 -toru inoue 10/05/30 16:07 

GWTでGINを使う


GWTでGINを使う

概要

    Google GINでの分割モジュールロードを実装する

    実はまだ匿名状態やコンパイル済みのモジュールとしては一般化できていない。

    お互いのことを知らなくても各モジュールを使用できる、という部分について、

    GINを使った状態での統一モジュールがまだ無い。


    →結論としては、まだ配布されている状態でのLazyなモジュールロードシステムで、GINに組み込まれたものは無いようだ。

        GWT2.0でのモジュール分岐はあるんだけどね。IOの映像を見るべきだな。


    

サンプルを実行してみる

    GoogleCode Gin関連 からサンプルっぽいソースを拝借、実行。 SVNからソースをチェックアウトする。

    そのなかのSamples>sampleが良さそうなので、チェックがてら使ってみる。

    http://code.google.com/p/google-gin/source/checkout


    0、ビルドできない

    理由は単純、AsyncProvider<T> instance 関連のソースコードがGinに含まれてないんだけど、サンプルには含まれてる前提のビルドが仕込んである。

    GWTが1.0から2.0に移行したタイミング移行、手を加えられているみたいだ。

    調べてみると、言及してる方がいた。

    http://reminiscential.wordpress.com/

    

    /**以下、引用させていただく


    Someone contributed a patch to gin, which made split points transparent to the user of gin. The presenters that aren’t needed initially can be wrapped in an         

    AsyncProvider<T> instance – which by the blessing of deferred binding, translates into a GWT.runAsync call in the generated code. The patch hasn’t been 

    accepted into gin’s trunk yet, but it’s fairly easy to apply the patch and rebuild. A huge thanks to fazal.asim who hacked and contributed this patch.


    以上。*/


    という事で、AsyncProvider周りについては、まだDLして使えるような状態ではない。

    (記事に出てくる議論と改修が行われてテストコードが書かれたのが3月、ダウンロードできる状態のプロジェクトは1月のもの)

    まあ、こういうこともあるよね。

    幸い今回試したいのは、単純なInjectionなので、まあ気にしない。


    AsyncProvider周りは孤立している機能なので、もろっとコメントアウトして実行。

    →更新(F5)を行うたびに、文章が変わるだけのテストプログラムが完成。


    本来なら、WidgetにAsync(非同期)な機能が実装されて、Widgetに"非同期実行"、"非同期詳細表示"、"エラー表示" ボタンがついて、実行される、、はずなんだけど。

    




言葉の定義

    モジュール

        機能の実装を呼び出すための関連づけをbindというプログラミング結合手段でまとめたもの。

        Guice/GINの目的は、異なるクラス間で、クラスファイル=機能に関連性を持たせること。


        ・コードによる結合

            設定ファイルとコードの同時性が保たれない問題を、設定ファイル=実行ファイルと一緒にする事で解消した。


        ・何でもバインディング

            全く無関係のクラスだろうと、モジュールという枠でもって処理を合致できる。

            物議をかもしそうだ。

            AsyncCallbackもこれで実装されている。


        ・インターフェースが確立されたアクセス

            インターフェースと実装をつなぐ事により、機能内容へのアクセッサを確保する。




使い方

    下記1~3を用意する。


1.Ginjectorを拡張したインターフェース

    メソッドの実装(メソッド名と型の実装)の記述を行う。

    


    メソッドを記述する。

    public TestPresenter getTestPresenter();

    このメソッドを外部から呼んだ際、あたかもシングルトンクラスや

    他の関連するクラスから取得したように見せかける事が出来る。

    また、それらのコードを書かずに実装できる。(BoilerPlateを書かずにすむ)

    続けてこのインターフェースに、モジュールとの関連付けをするコードを書く。


    @GinModules( { GuiceClientModule.class })

    インターフェースの定義を行う。


    

    で、出来上がったコードは下記。


GuiceInjector.java

/**

 * Injectorインターフェースサンプル

 * @author sassembla

 *

 */

@GinModules(//かっこでの複数設定が可能、モジュールとのひも付け

{

    GuiceClientModule.class//次に作成するモジュール

})

public interface GuiceInjector extends Ginjector {


    public TestPresenter getTestPresenter();


}

    

    作成したインターフェースは、下記のように書く事でインスタンス作成が出来る。

    GuiceInjector injector = GWT.create(GuiceInjector.class);





2.AbstractGinModuleを拡張したモジュールクラス

    下記のような名前のクラスを作ってみる

    public class GuiceClientModule extends AbstractGinModule


    先ほど作成したインターフェースから使用するクラスの、ひも付けの実装を行う

    (=実際に使用する際の使用法記述をコードに書く事で行う、ととらえるとわかりやすい。)


    AbstractGinModuleで抽象実装されているメソッドを実装する。


    protected void configure() {

    }

    このメソッド内に記述されたバインド処理が、

    呼び出すクラスをどのように扱うかを規定している。


    メソッドにbind内容を記述。ただのプログラミング。

    bind(TestPresenter.class).in(Singleton.class);//クラスをシングルトンインスタンスとしてこのモジュールに結びつけ、シングルトンとして指定。


    TestPresenterクラスの扱いについて、シングルトンクラスであるように設定している。

    こうしておくと、Injectorを通してモジュールに書いてある内容通りに特定のクラスがインスタンス化され、

    以後好きなときに呼び出せる。

    (ここまで読んだだけで全体がわかるならエスニックパーマでは無いほうのエスパーだと思う。 

        もちろん、呼び出される方についての情報に続きがある。)


    いちおうこのクラスのソースは下記。


GuiceClientModule.java

/**

 * モジュール

 * @author sassembla

 *

 */

public class GuiceClientModule extends AbstractGinModule {

    @Override

    protected void configure() {

        bind(TestPresenter.class).in(Singleton.class);//クラスをシングルトンインスタンスとしてこのモジュールに結びつけ、シングルトンとして指定。

    }

}




3.呼び出されるクラス(さっきからちらちら出てきてるTestPresenterクラス)

    もちろん実態(というか実装)が存在する。この部位が、当たり前だけれど好きに用意してくれていいクラス。


    いきなりソース

/**

 * プレゼンターの存在するクラス

 * @author sassembla

 *

 */

public class TestPresenter {

    /**

    * このプレゼンターに設定されているクラス

    * @param s

    */

    public void say(String s) {

        System.out.println(this+":"+s);

    }

}



    動かしてみよう!

    適当なEntryPointのあるクラスで、下記を記述すると


    GuiceInjector injector = GWT.create(GuiceInjector.class);

    final TestPresenter appPresenter = injector.getTestPresenter();

    appPresenter.say("hello Gin!");


    →コマンドラインに下記出現。

    hello Gin!


    もちろん、これだけ見ると

    「は? なんにも得してなくね?」

    となると思う。


    でも実際、TestPresenterクラスがシングルトンを実装しなければいけないクラスだったり、

    WebGLや物理エンジン、サウンドエンジンなどのステートマシン的なプログラムを必要とする場合、

    それらにいちいちシングルトン実装なんて書いていられるかというと、私はかなり嫌だ。


    Ginを使った今回の例では、シングルトンか否かはたった1行しか書いていない。




具体的な使用法


0.簡単な使い方(シングルトン実装)

    上記の例と同じ。


    シングルトン実装のコードを書かずに、隠蔽できる。


    final TestPresenter appPresenter = injector.getTestPresenter();

    appPresenter.say("hello Gin!");

    シングルトン性質は、injectorを通して取得、アクセスする限り保持される。



1.DIな使い方(連携)

    bind(ConnectionInterface.class).to(ConnectionImpl.class).in(Singleton.class);

    InterfaceにImplクラスをひも付け、特定のインターフェースを搭載したクラスを読み出す事が出来る。

    インターフェースを実装しさえすれば、どんな実装モジュールでもすげ替える事が出来る。

    →アップデートやメンテナンスにいいんじゃなかろうか。


    前提

        impl 実装クラスに@Singletonアノテーションが必要。

        impl 実装クラスのコンストラクタに@Injectアノテーションが必要。



    限定条件

        一つのインターフェースからバインドできるのは、一つの実装だけ。

        出来るのは、インターフェースAを実装したaについて、

        Aとaをつなげ、ボイラーコードの存在を無くす事。

           

        一つのインターフェースに複数の実装をバインドしようとすると、実行時にエラーを出す。

        

    実装をさらに拡張したオブジェクトがどうなるかについて

        ちゃんとクラスの型が異なるため、CastExceptionを吐いて終了した。



2.より広範囲で高度な使い方(チェーンする)

    存在しているのは、


    1.Injector

    2.Module

    この2つだけだが、自前でさらに広範囲のバインドを内包、行う特殊なModuleを作る事も可能。

    たとえば、自前のアブストラクトなModuleクラスを作成、AbstractGinModuleを継承させておく。


    継承をしたモジュール内では、自分用のBinderを定義する事が可能。


    下記のように、自前のモジュールを作ったとする。

    public abstract class AbstractChainModule extends AbstractGinModule {


    public AbstractChainModule () {

        super();

    }


    /**

    * bInterfaceに対して、aInterface2とaImplをバインドしたものをバインドする。

    * 

    * bInterface - aInterface

    *                     +- aImpl になる。

    * 

    * @param <A>

    * @param bInterface    

    * @param aInterface2

    * @param aImpl

    */

    protected <A extends aInterface> void bindAB(

    Class<? extends bInterface> bInterface,//抽象的な(仮の)bインターフェースを拡張したインターフェース

    Class<A> aInterface2,//クラスAのインスタンス a、この時点でAaInterfaceを拡張したものなので、aはインターフェース(さすがにこのへんは暗黙)

            Class<? extends A> aImpl//Aのを拡張したインスタンス aImpl

            ) {

                bind( bInterface );//先ずbImplをバインドし、

                bindA( aInterface2, aImpl );//aインターフェースにaの実装をバインドする

    }



    /**

    * 入れ子実装

    * aInerfaceにaImplをバインドする。

    * 

    * @param <A>

    * @param aInterface

    * @param aImpl

    */

    protected <A extends aInterface> void bindA( Class<A> aInterface, Class<? extends A> aImpl ) {

        bind( aInterface ).to( aImpl );

    }


    入れ子構造にする事で、モジュール同士を連結させたり、内包させる事が可能。

    Guiceでは、サーバサイドでのモジュール寿命(一回ごとに毎回生成、キャッシュに関連づけて、、など)について、

    制御を行う旨がある。

    もうDIっていう範疇じゃない。

    この時点まででGoogleIO2009で発表された全コンディション情報の1/3程度でしか無い。


    GoogleIOの2010を見る人、行った人、是非お話聞かせてください。


    


3.サーバサイドとbind(RPC)

    ここから先に、GWTでもてはやされているRPC(Remote Procedure Call)がある。

    GINやGuiceが生まれた背景をしっかり調べると、けっこう楽しい事をしているのがわかってくる。

    言語と、その言語を実行する環境を使っての、スマートな”依存関係の解決”と”資産の最大化”に向かってるんだろうな。


    


注意点

    Developmentモードでの使い方について、Inject系の処理は一度モードを落とさないと、変更点が加味されない。原因は不明だが、キャッシュ系?

    →読み込まれているスクリプトの問題だった。リロードで解消したり。



今後の展開

    もう少しがんばると、LPC(Local Procedure Call)が出来そうな気がする。


    魔法の名前一致でセントラルを作る。セントラルからモジュールの枝葉をのばすと、

    お互いのモジュールの存在を知らなくても、通信できるようになる。

    わーい、iPhoneと同じ完全相互非依存プログラムが出来るぞー。

    DIとは全く別の話だー。


公開完了 -toru inoue 10/05/30 15:45 


フォロワー