2011年8月19日金曜日

ToJSCompilerとしてのGWTについて

ToJSCompilerとしてのGWTについて 


概要
    GoogleWebToolkit GWT 
        (発音はグウィット 2009年ころにIOで突如言い出してた気がする。)

    Googleが作ったJava言語を利用したJSコンパイル技術。FWではない。
    Java to JSの変換技術。
     ToJSCompiler(てか正確にはCompile to JS かな。)

    ・Javaで記述、コンパイル結果がJavaScript(JS)として実装、実働

    ・Javaのメソッドやクラスが使える

    ・Eclipseなどと連携可能
        ステップ実行ができる、プラグインが使える、などなど
        鬼便利というかこれが肝コレだけコレが全て

    ・JUnitが使える、テストが可能

    ・JavaScript単体では書けないような範囲の物事を、
        Javaの型安全な世界で記述する事ができる

    ・JSのローディングやテストを、Javaに関連する世界で自動化できる

    ・あらかじめ用意されているライブラリがたくさん
        イベントリスナ、JSON、JSONP、
        GUI Widget(ダサい。Apple並みとは言わないまでも、、)、
        Canvas、Sound、他

    ・JSも使える Java中JS、JS中Javaが可能
        JSNI(JavaScriptNativeInterface)


落とし穴もがっちりある
    JavaかとおもったらJSだった。何を言っているかわからねーと思うが(ry

    ・変換不可能なクラスもある
        日付に関するクラスとかが無い。めんどかったんだと思うが。

    ・Widgetが破滅的にダサい
        グラフィカルな面で本当に残念です。ありがとうございます。

    ・ロードとstaticの関係
        staticなどを使うと、優先的にLoadingが組まれる。結果として、
        名前空間が効かないポイント(=衝突を考慮する必要がある部分)が生まれたりする。
        =PureJSと同じ駄目さ

        Javaであればリフレクションなどの手段で明確にアクセスできるところ、
        偶然名前が一致して衝突、などがあり得る。


    ・イベントの解除などはJSの癖を引きずる
        イベントへのアイデンティファイに対して、制約が多い。根源がJSのリスナなのでしょうがない。
        具体的には、特定のオブジェクトのみリスナから外す、という事ができない。
        オブジェクトが帰属するクラス単位でのリスナがごっそりと消える。
        (リスナのアイデンティファイについて、クラス単位より小さな単位でのアイデンティファイができない)


    ・JSNIはJSなので何が起こってもおかしく無いし補完が効かない
        オハコンの中のオワコン


ところでJavaScriptとはなんだったのか
    GWTのようなToJSCompilerが生まれた経緯を推察してみる。

    JSとは、
    HashMap a ... b
    b ( =a)
    a (=b)
    a(function b()) など。

    何でも連鎖マップに入れられ、発火させられる言語
        →他の言語でやっている様々な事が、ほぼ、JSを使って、JSの上で実装可能。


ここに闇がある
    ☆他の言語でやっている様々な事が、ほぼ、JSを使って、JSの上で実装可能。

    →言語の中に、同じ言語を使って、機能や仕組みを実装する、という行為には、元来無理がある

    だって元々その言語に無いのだもの。
    ・内部にむき出しの実装が増える事によって、トラブルが増える
        「実装した機能」それ自体の実装に触る事ができてしまう
        e.g. C++のスマートポインタ、Javaのメッセージング


    JavaScriptの場合は、元来無いものが非常に多い。
    名前空間(致命傷)、クラス、メッセージング、自己環境把握概念

    ・実装機能と自分が書き足したものとの区別がつくのは今この瞬間の書いている自分だけ
        a = a+b;        (before)
        a = a+b+c;    (after)

        →    1D後、1W後、1Y後に見て、何処が「足された部分」か、自分や他人にわかりますか? ッつー話。
    

    ・トラブルを起こさないように実装するには、階層を分けてのFW化(e.g. RoR)、ルール化が有用だが、。
        ルールが増える事(ルール爆発)は自殺行為→多彩なルールを守る事にコストがかかってしまう。
        しかもそれは永遠に続く。


    →解決策として、コンパイル という「改変」行程が選ばれる。



JSをコンパイルの結果として作りあげる技術たち ToJSCompiler

    Google Closure Tools (JS to JS コンパイル)
        http://code.google.com/closure/
        強くルール付けされた構造を模倣する事でのプラグイン化
        自己制約をパッケージ化する

    CoffeeScript (Coffee to JS コンパイル)
        http://jashkenas.github.com/coffee-script/
        JSの穴をあらかじめ殺した記法での記述と、コンパイル処理による最適化、ネームスペースの補助
        RoR3系で色々動きがあるらしいが?よく知らない。
        これからJSをどうしても書かなければ行けない分野では来ると思う。

    GWT (Java to JavaScript コンパイル)
        http://code.google.com/webtoolkit/
        Googleが用意した特定のクラス、メソッドがJSに変換される。
        コンパイル処理による最適化、パッケージによるネームスペース明示、
        staticによるシングルトン明示などができる。
        おまけでブラウザ間の差異を勝手に吸収する。
        Java言語自体に素敵さが足りないので、後述のJSCompilerたちの方が先があると思う。

    Pyjamas (Python to JS コンパイル)
        http://pyjs.org/
        触った事無いからわからん

    Js_of_ocaml
        触った事無いからわからん

    ClojureScript (Clojure to JS コンパイル)
        https://github.com/clojure/clojurescript
        さわり中 まだよくわからん

    ScalaJS (Scala to JS コンパイル ? 未登場)
        まだ無いのでわからん。作ってるらしー。 自分的に本命。
        現在のactorの挙動とか、JSフレンドリーなんじゃないかなーと思ったり。
        メソッドを渡す方法が効率的に記述できるようなバックドアが着いたら、
        ぼくのかんがえたさいきょうのげんご に近づく。
        理由は参照コピーと同義だから。


A to JavaScript の利点
    とあるA言語の能力 >>>>>> JSの能力 である前提がある。

    Aという言語があり、ルール的にJavaScriptよりも厳格 かつ、機能が定義されているとする。
    名前空間、記法制限、型、演算子、メッセージング、クラス、構造体、列挙子、、、

    これらを、その言語で書き、JSにコンパイルする。

    元々のAという言語にある機能を、Aという言語の記法で使う範囲でのみ担保すればいい。
    →最終的に出力されるJSには、手を触れる事が無い(あるとしたらA to JSコンパイラのバグとか不備)


    例えばクラスをJSで実装する場合、
    JSで直に実装→JSを書く際に、その自己定義した構造にあわせたreadとwriteが必要になる
    →ルールを言語の内側につくるので、さらに内側に書くしかない。

    他言語で書く場合
    →ルールは記述時言語側が持っているため、書き手は意識しないでいい。
    →コンパイルされた結果は、ルールが構築されたJSの中に、手続きが記述された状態になる。
    →結果は同じであっても、人が煩わされる行程が減っている、自動化できている事に注目。


ToJSCompilerとしてのGWT
    締めに、JSCompilerとしてのGWTの特性を上げる。

    ・Java記法で書ける
    ・パッケージでの名前空間の保護ができる
    ・JSNIで、JavaとJSがつなげる。JSNIは先行変換される部分記述のようなもの。
    ・最終的には結局JSに変換される

    特筆すべきは「結局JS」という部分。
        JavaとJSのハイブリッドの意味や価値がここにある。

    Pure Javaではできなかった、
    メソッドのオブジェクト化などがJava記法とJS記法の組み合わせでできる。

        private native JavaScriptObject get () /*-{

        return @com.kissaki.client.MessengerGWTCore.(略)::mtd(Ljava/lang/String;); 

         }-*/;



        これはどうよ。凄くないか。


        mtdメソッド
        public void mtd(String str) メソッドを、JavaScriptのオブジェクトに変えている。
        バリューとJavaのメソッドを関連づけたり、メソッド自体を疑似ポインタとしてぶん投げることができる。
        
        おそらく他の言語でも、JSでしかできない事を担保するために
        従来の言語の記法を拡張してブリッジにするような目論みとして、
        GWTにおけるJSNIみたいなものが出てくるはず。


        
今の俺の結論
     ToJSCompilerオハコン。
    言語の中に言語で機能を追加する副作用を回避できる。
    ブラウザで動く言語がJSに限られている事が一因だが、今後は異なるといいなーとか。JSのNativeライブラリ化とか進むといいなー。

(追記)タイトルをToJSCompilerに変えた。JSCompilerだとJSをコンパイルするように見える、と指摘受けた。11/08/23 11:40:33

2011年2月1日火曜日

iOSでのTest SenTestingKitについて

iOSでのTest SenTestingKitについて


概要

    iOSでのテストに使える、SenTestingKitの導入と解説



SenTestingKitとは

    http://developer.apple.com/tools/unittest.html


    iOSで使えるテスト用のフレームワーク。デフォルトで入っている。

    ソースコードでテストを書き、ビルド時にテストを行う。

    実行時ではないのがポイント。



手順

    1.ターゲットを作る

 

        ターゲットの作成が完了するとウインドウが開く。

        ここで、このターゲットが依存する実行可能ターゲットとか決められるんだけど、

        説明が長くなるのでパス。閉じる。




    2.アクティブなターゲットをSomethingTestに設定する



    3.テストのソースコード書く

    .h.mに別れるのが好ましくないので、SomethingTest.mという名前のソースのみ作成。



ソース:SomethingTest.m


#import <SenTestingKit/SenTestingKit.h>

#import <UIKit/UIKit.h>


@interface SomethingTest : SenTestCase {}

@end



@implementation SomethingTest


- (void) setUp {

    NSLog(@"setUp");

}


- (void) tearDown {

    NSLog(@"tearDown");

}


- (void) testSomething {

    NSLog(@"testSomething");

    STAssertTrue(FALSE, @"here comes");

}


@end


    もし、2を行わずに3を作った場合、ターゲット[SomethingTest]の、

    [ソースをコンパイル]の中に、SomethingTest.mが入っていないので、

    エラーが出ると思う。おとなしくD&Dで足すと、実行出来る筈。




    4.実行。

        このソースだとSTAssertが必ずFALSEなので、⌘+Bでビルドすると、

        ビルド時にエラーが出る。

        失敗(!)2 のとこをクリックすると、ビルド結果の表示がされる。

        ▲を押して潜って行くと、(テストを通らなかった)原因の内容を見る事ができる。

        STAssertの行を消すと、今度はエラー要因が無いので成功する。



以上。


STAssertTrueの他に、Equalsなどがある。



アレなところ

    成功するとどんなテストに通ったかとか見えない。


    setUpとtearDownがポインタの関係で非常にシビアになりやすい。

    tearDown後に落ちる場合はまずその辺りを疑う。


    テスト中にエラーが発生するともれなくテストのエラーが飛ばされる

    = Obj-Cのコンソールにエラー原因が出るような事が無い ので、むしろ悩む場合がある。

    実際にEmuや実機でテストの内容を実行(いろいろ手を加えて通常ターゲットから起動)して見ないと解決出来ないしょぼい私を許して。



今後

    非同期テストについては今後記述を足して行く。


2010年10月12日火曜日

iOS用メッセージングライブラリ:MessengerSystem

iOS用メッセージングライブラリ:MessengerSystem



概要

    クラス間親子関係メッセージング用ライブラリ。 フルObjective-C。

    オープンソース。

    iOSのObjective-CランタイムでサポートされているNSNotificationを利用し、

    MVC -MVC 間の接続度を可能な限り疎にする。

    


    このライブラリのインスタンスを持つオブジェクト同士を任意に接続し、

    メッセージを投げ合う事が出来る。


    また、オマケで、アプリケーション内での接続内容をリアルタイムに可視化する

    外部視覚化ビュー、

    通信ログを持つ



    目標A、タグ:バリュー型での入力を可能にする

        Dictionaryをつれ回す形式はそのままだが、

        値に対して、文字列型の値を付けられるようにする。


    目標B、親子関係の動的指定

        親子関係を、子供から親を指定する手法で

        設定できるようにする。

        複数の親は許容しない。

        複数の同名の子供が存在する事を許容する。

        

    目標C、メソッドの外部呼び出し

        メソッドのポインタを渡し、受け取り側から遠隔実行できるようにする


    目標D、可視化

        つながりを可視化する

        可視ビューを作り出し、各インスタンスの関係、つながりを表示できるようにする。

     

    目標E、ログ取り

        通信記録を取れる/見れるようにする。


    目標F、遅延実行、遠隔実行

        遅延実行をタグ設定で実行できるようにする。



DL
    GitHubにアップロードされている。
    http://github.com/ToruInoue/MessengerSystem


APIドキュメント
    doxygenにて作成、添付


使用法
    1.MessengerSystemのインスタンスを持つ
        初期化時、自身のクラスidと、
        メッセージが来たときに実行したい、NSNotificationを引数に持つメソッドと、
        このMessengerの固有名詞を設定します。

- (id) initWithBodyID:(id)body_id withSelector:(SEL)body_selector withName:(NSString * )name

        
        Ex:TEST_PARENT_NAME = (@"親設定のMessenger"), TEST_CHILD_NAME_0 = (@"子供その1")と定義しておいたとする。

MessengerSystem * child_0 = [[MessengerSystem allocinitWithBodyID:self withSelector:@selector(testChildMethod:) withName:TEST_CHILD_NAME_0];





    2.クラス間を跨ぐように、Messengerどうしに親子関係を設定する事が出来る
        inputParentメソッドで他のクラスのMessengerの固有名詞を入力すると、
        入力元のMessengerを子供、固有名詞を指定されたMessengerを親として、
        通信関係が構築されます。

        とあるクラスA
MessengerSystem * parent = [[MessengerSystem allocinitWithBodyID:self withSelector:@selector(testParentMethod:) withName:TEST_PARENT_NAME];

        とあるクラスB

MessengerSystem * child_0 = [[MessengerSystem allocinitWithBodyID:self withSelector:@selector(testChildMethod:) withName:TEST_CHILD_NAME_0];

[child_0 inputParent:TEST_PARENT_NAME];


    その時のMessengerの関連を表示するビュー
        (MessengerViewControllerのview要素をwindowにaddSubViewしたもの)
    MessengerViewController親子関係をグラフィックで見る事が出来る。

        
    3.親子間でメッセージを送る
        可変長引数のNSObjectを渡す事が出来る。ただしnilで締める必要が有る。忘れるとエラー。
        
        parent → child_0
[parent call:TEST_CHILD_NAME_0 withExec:@"テスト",

 nil];



        child_0 → parent
[child_0 callparent:@"テスト",

 nil];  

        


        メッセージの受け取りは、
        Messenger生成時に指定したメソッドで行う事ができる。

    parentインスタンスを持っているクラス
- (voidtestParentMethod:(NSNotification * )notification {

    NSMutableDictionary * dict = (NSMutableDictionary *)[notification userInfo];

    NSString * exec = [parent getExecAsString:dict];


    if ([exec isEqualToString:@"テスト"]) {

        //やりたい事

    }

}




    childインスタンスを持っているクラス
- (voidtestChiidMethod:(NSNotification * )notification {

    NSMutableDictionary * dict = (NSMutableDictionary *)[notification userInfo];

    NSString * exec = [child_0 getExecAsString:dict];


    if ([exec isEqualToString:@"テスト"]) {

        //やりたい事

    }

}


    kvsでの値受け渡しが可能。

[child_0 callParent:TEST_EXEC_3,

 [child_0 tag:@"タグ" val:],

 nil];

 


   

    4.ブロードキャスト/相手を確定して通信
        親→子へは、子供の名称でのブロードキャストが可能。
        同名の子供が何人いても、メッセージを送付できる。

        子供の子供、などのネストが可能。
        


    5.遅延実行、遠隔実行
        命令の遅延実行(floatで指定した秒数後に起動)、
        自分が持っているメソッドの遠隔実行
            (受取手側から引数を入力してのメソッド実行)
            などが可能。

             
        parent → child_0 遅延実行
            0.3秒後にメッセージを送る

[
parent call:TEST_CHILD_NAME_0 withExec:@"テスト",

 [parent withDelay:0.3],

 nil];




        child_0 → parent 遠隔実行

            child_0を保持しているクラスが持っている、下記
        - (void) sayHello:(NSString * )str;
            メソッドをparentを保持しているクラスで遠隔実行

[child_0 callParent:TEST_PARENT_INVOKE,

 [child_0 withRemoteFrom:self withSelector:@selector(sayHello:)],

 nil];



            受け取ったparent側で、引数だけを渡して実行!

- (voidtestParentMethod:(NSNotification * )notification {

    NSMutableDictionary * dict = (NSMutableDictionary *)[notification userInfo];

    NSString * exec = [parent getExecAsString:dict];


    if ([exec isEqualToString:TEST_PARENT_INVOKE]) {

        [parent remoteInvocation:dict, @"遠隔実行で親から子供の、子供から指定されたメソッドを実行しています。", nil];

    }

}

  



    4.親子関係の動的変更
            親から子をパージ、子から親をパージ、などすると、子から親を再指定できるようになる。
             動的に変更可能。
        [child_0 removeFromParent];

        [parent removeAllChild];



ライセンス
    未定。とりあえず数日だけ公開。
    BSDかGPL2。
    このライブラリを使用した事によるどのような損害、被害についても弊社はその責任を負わないものとする。


    







2010年10月9日土曜日

doxygenでObjective-CソースからDoc生成

doxygenでObjective-CソースからDoc生成


概要
    Objective-Cのソースに対して、JavaDoc形式コメントから
    HTMLなどでドキュメントを作成してくれるツール、
    doxygenについての導入メモ
    
    もちろんC++,Cにも使える。
    (というかObjective-C専用の設定は無かった。
        だがウマく出たので良しとする。)
    

目的
    Objective-Cプロジェクト中に、JavaDoc形式で書かれた文言から
    ドキュメンテーションを自動作成する。
    といっても、動作原理はJavaDocと変わらない。
    記法もJavaDocそのものなので、
    @paramとかの記述にも対応してくれる


インストール
    Mac向けのPackageで用意されているので、DLしてインストールする。
    Wizardに従う。

    doxygen
        http://www.stack.nl/~dimitri/doxygen/


使い方
    GUIがある。
    doxygenをインストールしたフォルダにappがあるので、起動。
    先ずは生成されるドキュメントのタイトルとかをセットする。

    Step1
    プロジェクトの置いてあるフォルダを指定。

    Step2については下記、
    Project name,versionは適宜。
    Source code directory 
        ソースが置いてある場所を指定。
        iPhone系であれば、classファイルのフォルダを指定するだけでOK。
        
    Specify the directory where doxygen should put ~
        doxygenがドキュメントを出力する場所について、指定する。
        Step1をこなせば、プロジェクトの置いてあるフォルダ近辺が自動入力される筈。
    次に、実行する。
    Runのタブを押し、Run doxygenボタンを押す。以上でドキュメント生成が完了する。
    Show HTML output を押すと、完成したドキュメントが表示される。
    内容をもっとJavaDocらしくきちんと書けば、return,paramなども表示される。
    なかなか使えるんじゃなかろうか。


その他
    Graphviz というクラス関連図描画ソフトと連携しているらしいのだが、
    どうも出力時にエラーが出るようで、まだ正確に使っていない。

    Graphviz
        http://www.graphviz.org/

2010年9月27日月曜日

GWT Designer

GWTDesigner について


概要
    GUIがある、Webページデザイン用のEclipseプラグインについてです。
    GWTでのGUIデザインを視覚的に行うことができ、さらに外部からインスタンス化する事が非常に簡単。
    GUIパーツを簡単に作り出す事ができます。
    



ライセンス登録
    サイトから行う。
    →Googleによる買収が完了。ツールが無償で提供されるようになりました!    やったね。 -toru inoue 10/09/XX 18:29 


使い勝手
    めっちゃいい。
    重量があるのがネックだが。
    詳細は今後書く。
    ・ひな形クラスで、ビュー(MVCのView)として使える要素が手軽に作れる。
    ・レイアウト手段として、入れ子の定義などがGUIで手軽に行える。
    ・ソースコードへの編集に対応しており、描画インスタンスの追加、変更、
        シングルトンなどの変化も即座に反映される。











2010年9月24日金曜日

iPad から VGA出力

iPadからVGA出力



概要
    iPadに専用VGA出力コネクタを繋いで、iPad上の画面を転送するプログラム
    参考はGemmelさんの下記記事。いつも大変参考にさせていただいています。
    http://mattgemmell.com/2010/06/01/ipad-vga-output
    Thanks a lot! Matt!


制作内容
    手順はかなり簡潔で、

0、インスタンスを用意する
    UIWindowexternalWindow;

    NSArrayscreenModes;

    UIScreenexternalScreen;


1、外部スクリーン数を取得し、1より多い=外部スクリーンがある、と見なす。
    if ([[UIScreen screens] count] > 1)

2、外部スクリーンをインスタンスとして取得し、所持する。
    externalScreen = [[[UIScreen screens] objectAtIndex:1] retain];

3、そのスクリーンが取り得るスクリーンモード、サイズ情報をNSArrayで取得する
    screenModes = [externalScreen.availableModes retain];//スクリーンモード

4、スクリーンモード配列から目的のモードをUIScreenModeとして取得し、
    外部スクリーンインスタンスにモードとしてセットする。

    UIScreenMode * desiredMode = [screenModes objectAtIndex:目的のモードが格納されているインデックス];

5、外部スクリーンモードインスタンスを自作の外部ウインドウインスタンスにセットする
    externalScreen.currentMode = desiredMode;

6、指定したUIScreenModeからサイズを読み出し、外部ウインドウインスタンスのサイズとしてセットする
    CGRect rect = CGRectZero;

    rect.size = desiredMode.size;

    externalWindow.frame = rect;


7、外部ウインドウインスタンスをiPadが使用するウインドウとしてセットする
    externalWindow.hidden = NO;

    [externalWindow makeKeyAndVisible];




2010年7月12日月曜日

NGを画像化する

NGを画像化する


概要
    知り合いのプロジェクトで、見た目にこうなったらNG、そのときのNGの種類を客観的に判断できるよう
    シート化してある物があった。

    →判断の他人化、他人がバグを見分ける際に、まとめておくと凄くいい! という例。

    モノがグラフィカルなだけに、こう見えたらこれだ! と言ってね。
    もしかして、、、をバグ発見に用意する、というアイデア。

    不測のバグに対して悪影響を生みそうだが、グラフィカルなバグに関して人の目で
    チェックをかける価値はやはり捨てられない。

    不測のバグであるか否か、を判断するためには、報告を受け直した際に、確認が必要。
    運良く(悪く?)直っていなければ、という、Luckが必要な手法だけれど。

    不測のバグなら、新たなバグコレクションとして例を足せばいい。
    
    
    そのバグが何に起因するのか、というのをプログラマなり問題解決者に伝える際、
    見た目にわかりやすい例は、現状でのまっとうな解の一つだと思う。

フォロワー