2010年5月10日月曜日

勉強: マルチタスクプログラミング

本格的なマルチタスクプログラミングは初めてだ。勉強した事を纏める。
1:セマフォー(Semaphore)とは
マルチタスク環境化で、どれだけのプログラムを並列にして走らせるかを決める為のもの。
P操作とV操作からなるらしく、initialize,finalizeとほぼ同義。ただし、initializeをする時に
セマフォー変数を1減算して、そんでもってfinalize時に1加算する。これによって、管理するんだが
何故、そんなことで管理できるかと言うと理論はとてもシンプルで。。。
 一回に定員3名まで実行できる人がいる。
  ここに対して、処理をやってくれとお願いに来る人が4人来る。
 始めの3人は全然問題ないので、一気に実行する。
 一人実行が開始される毎に、定員が1ずつ減っていくので3⇒2⇒1と減っていき、
 3人目の実行が開始された時点で0人の定員となる。4人目はやってきても、
 もう入る余地がないから、待つ。一人目の人が処理終了になった段階で、
 定員は1増える。この段階で待ち状態であった4人目の処理が開始され再び定員が0
 となる。
とまあ、こんな感じで部屋に対して入ったり出たりする最大数を定義するのがセマフォー変数。
この一連の処理のことをセマフォーと言うそうで。間違ってたら突っ込んでください。。。

2010年3月11日木曜日

フレームワーク奮闘記 その7 AOPとか思ったけど、もっとコアからだな。

今回、モデル周りの抽象化をしようと思って、色々とJavaについて知らないなぁと思って反省。
AOPだ!とか思ったけど、もっと基礎のところから、勉強をせねば。
まずはJNDI、WASがうちのAPだから、ここらへんからスタートだね。

JNDIとは、Java Naming and Directory Interfaceのこと。
もの凄いザクっというと、他のサービスやなんやらに、階層的にアクセス出来るインターフェイスだってこと。裏側にはLDAPだとか、ファイルシステムとかが来る。
それゆえに、データソースから値をとるときに、特定の命名規約にのっとってアクセスが出来るわけだ。

我が家の中でも結構、適当に使われていて、コード的には以下の部分になる。
InitialContext ctx = new InitialContext();
 DataSource ds = (DataSource) ctx.lookup("jdbc/Database");
とか書いてある部分。
これも、ファイルシステムの中にアクセスするとか、jdbcにアクセスするとか言うことを
一元的にJNDIが引き受けてくれているから出来ることらしい。
腐ったコードだと思っているところにも、思わぬ収穫があるもんだ。勉強になるなぁ。

InitialContextには引数をとれて、Propertiesを放り込むことが出来る。
書式的には、下記の通り。
Properties props = new Properties();
 props.put(Context.INITIAL_CONTEXT_FACTORY, "<サービス・プロバイダーのファクトリー・クラス名>");
 props.put(Context.PROVIDER_URL, "<サービス・プロバイダーを示すURL>");
 InitialContext ictx = new InitialContext(props); 
なるほどねぇ。
ここまでは、下記のリンクで勉強しました。

今さら人に訊けないJNDI

JNDIが何ものなのかはとりあえず分かった。
これで、MainServlet内に書いてある。InitalContext.lookup()が何やってるかも理解できた。
次は、どうやってSpringのapplicationContext.xmlに設定するかだ。
でも、これは意外と簡単に解決してしまった。そもそも、検索をする際のキーワードに
JNDIというキーワードが頭の中に無かったので、検索出来なかったのだ。
さすが。。。JNDI。。。おそるべし。
ちなみに、Springでは下記のように設定するらしい。jdbc/以下のDatabaseは可変だから。
設定した人に聞かないと分からないですが。。。

さて、次はログだな。MethodInterceptorとかThrowAdviceとか。
色々謎の単語が飛び交ってるけど、1つづつ片付けて行きますかねぇ。。。

2010年3月5日金曜日

フレームワーク奮闘記 その6 ちょっと寄り道してAOP

Springを導入しようと思っていて、Webページやら何やらを色々と読んでいると
どうやら、Springに対して大いなる誤解をしてるらしいことが判明。
完全に調べきってないけど、下記の懸念点をSpringで解決しようかなぁと思ってみている。
  • ログ


  • バッチ


  • メール


  • Ajax用のレスポンスServlet


  • でまあ、当初の目的はConnectionの隠蔽とトランザクション処理の追い出し
    だったんですが。
    今回はちゃんと勉強します!
    いつもいつも忙しさにかまけて(それを言い訳に。。。)
    表面的な理解で終わってしまう僕ですが、
    今回ばかりは皆の仕事の土壌(Soil)を正に作っているわけだから、
    きちんとした理解をするべきだ!という結論に至りました(当たり前だ!)。
    というわけなので、今回は大分寄り道をしてAOPの勉強です。

    2010年3月2日火曜日

    フレームワーク奮闘記 その5 何となく出来てきた。

    どうも、完全に一ヶ月間放置してました。。。
    ところで、まあ良い感じで仕上がってきたので、経過報告がてら現状の問題点とかを。。。

    管理方法は以下の様にする。
    Service
         |__ MainMenu
         |__ SubMenu
         |__ Contents
                |__ Page
    
    それぞれのコンテンツに対してライフサイクルを設ける。
    GlobalSession管理<アプリケーションスコープでのSESSION>
          |__ MainMenu
          |__ User情報とか
          |__ セキュリティ情報とか
    ServiceSession管理 
         |__Service
          |__SubMenu
          |__Contents
                |__ Page
    
    実際にちょこまか使うのはContents配下のPageたちなので、ContentsとPageはまた別個に持つ。
    これって良く考えると、ServiceSessionいらないんじゃないかと思うんだけど、まあいいや。
    イメージ的に下の様な感じ
       request.getSession().setAttribute("SoilServiceSession",new HashMap);
       //このHashMapのObjectに更に色々詰めていく。
      Map sessMap = (Map) request.getSession().getAttribute("SoilServiceSession");
       sessMap.put("SoilContents",new Contents());
       sessMap.put(contetns.getClass().getName(), new HashMap);
      //キーを常に管理しておいて、必要なくなればnullを突っ込んで参照を切ってしまう。
       //contetnsは飽くまで管理上の区分けなので、表側には殆ど出てこない。。。
    
    てな感じで管理しようかなぁと漠然と思っている。何か良い方法無いのかなぁとも思いつつ。
    後、この形にしたことで少しずつAnnotationの有用性も出てきた。
    まだまだ、世にあるフレームワークには程遠いけど。。。
        @Control(next = Next.class,
                 back = Back.class)
        public abstract class Page{
    
            public void process(){
                   
            }
        }
    
    上記の様な感じ。抽象クラスなので実際に呼び出されるところでAnnotation使って、
    自身の管理する次のクラスと前のクラスが分かるようにしてみた。
    描画部分はVelocityで、そんでもってAction系の所は意外と普通にReflectionで作ってしまったので、
    ほとんどエセRuby on Railsな感じになってきている。
    ある程度、まとまったらもう少し奥歯に物挟まっていないような感じで書いてみたいもんだ。
    本気で良い感じなってきたら公開してしまうのもありかなぁと。。。
    もともと、オープンソースな土壌で生まれ育ったから、そこら辺は死守したいですな。
    とまあ、良く分からない感じですけど、駄文におき付き合い頂きどうもでした。

    2010年2月2日火曜日

    フレームワーク奮闘記 その4 ライフサイクルって難しい。。。

    以下の様な感じにすることになった。

    Soilの責務はサービスのライフサイクルの管理
    サービスは自身の管理するメニューを持つ。
    メニューをクリックすると、実際のアクションが走る。
    だから、Soilはサービスのコントローラで、実際的なMVCのコントローラは
    サービス。サービスから実際の業務画面の描画やビジネスロジックが乗っていくことに。
    ここで、問題。
    Soilはサービスのライフサイクルを管理するんだけど、サービスは
    自身の中で複数のメニューを持つわけ。
    サービス1
       ○○届け
       ○○申請
     サービス2
       ▼▼届け
       ▼▼申請
    
    みたいな感じ。
    と言うことは、サービスはどこまでSessionを持ち続けるべきなのか?
    今のとこは、違うサービスがリクエストで通知されるまではそのサービスの
    Cacheは持ち続けることになっている。ここは、アプリケーションの肝出し
    如何様にでもなる分だけ、直接的に速度に関わってくるところでもある。。。
    かなり難しい部分です。
    サービス1
       ○○申請
       ○○届け
    
    実際には、リンクなり何なりを叩いて○○申請に遷移するわけだから、
    ○○申請に要るというCache情報を持ち続けていればいいのか??
    ○○申請⇒○○届けに連続性は無いのか?
    果たして、その部分のCache破棄しちゃっても大丈夫なのか?
    うーん、難しい。
    ここ、本当に難しい。
    どうやって解決した方が良いのかな??
    悩みます。今日も(笑)

    2010年1月28日木曜日

    フレームワーク奮闘記 その3 ServiceMapって?

    少し進展があった。
    下記の様な構成でとりあえずモックを作ってみることにする。
    Soil --> グローバルコントローラ
      Service --> サービスコントローラ
        Context --> コンテキスト(文脈)は何でもあり。
    
    Soilは複数のアクションを持つわけだけど、そのアクションを特定する方法が今回の課題。
    RailsだとRoutes.rbに相当する部分。
    やはり、WebApplicationだからincoming request,output responseという概念は
    代わり無いので、何かしらのリクエストをキーにするしか方法が無い。
    今回、面倒なのは、
  • Soilは複数のアクションを持つ


  • 複数のActionは関連性を持つ


  • というところ。
    複数のアクションの関連性を定義する為に、地図が必要になるわけだ。
    Soilが何もかもしる必要は無いので、イメージとしてはSoilは地図を持って
    指定のサービスをつまみに行くイメージ。
    呼び出し口は下のようになるのかな?
    class Soil{
           public void dispatch(HttpServletRequest req){
                String param = req.getParameter('???');
                String serviceName = ServiceMap.find(param);
                Service srv = (Service) Class.forName(serviceName).newInstance();
                
                if("DONE" == service.getStatus()){
                      next();       
                }else if("PROGRESS" == service.getStatus()){
                     current();
                }else if("BACK" == service.getStatus(){
                     back();
                }else{
                     //error
                }
           }
       }
    
    この中のここをどのようにしていくか?
    String param = req.getParameter('???');
    String serviceName = ServiceMap.find(param);
    
    これが問題だ。

  • そもそも上記のように全てのリクエストをバイパスする必要があるのか?



  • リクエストを後段に渡すことで、サービスのインスタンスを作るのが役割だから。
    これは仕様が無いんだろうな。まだそこをどうラップするとかは考えてないけど。。。

    リクエストが必要だとすれば、判定すべきは最初のリクエストだけなのか?
    最初のクラス名さえ分かってしまえば、その後どのようにしていくのかは
    自ずと決まる。それを定義するのがServiceMapの役割だから。
    となると、もう少しコードの書き方も変わって来るのか?
    うーん、少し苦しくなってきた。考えがまとまったら、続きを書くことにしよう。

    2010年1月23日土曜日

    フレームワーク奮闘記 その2 当たり前を考える。

    完全に備忘録。
    Soilがカバーするのは業務。
    MVCに分割するのはもうちょっと後で良くて、まずは守備範囲を考えてみる。
    まだまだ、思考/試行しながら書いているのまとまりが無いのは御免!
    SoilはService,Document,Detailを管理するのが責務。
    Soil: 全ての土壌
     Service: 提供するサービス
      Document: 提供する書類
       Detail: 明細
    
    そして、Soilは複数のサービスで構成される。(コードはイメージ)
    class Soil{
     Service getService(String serviceName);
    }
    
    サービス間には連携があるはずで。サービス間の連携は自身が知っているはず。
    しかし、連携の大元は別にあるべきか?? --> これはそのとおりなはず。
    class Soil{
            Service getService(String serviceName);
     List getRelatedService(String serviceName);
    }
    
    --> ここ微妙(T0T)

    となると、連携していた場合、次の段階に進む為には、
    自身の状態を通知出来無ければならない。
    class Service{
     Status getStatus();
    }
    
    と考えると、関係性がある場合は以下の様に表現されるべき。

    サービス間は順次処理がされていく。 sequence
    Service1 --> Service2 --> Service3

    サービスの連携先はいずれかである。 selection
    Service1 --> Service2
    --> Service3

    サービス1とサービス2に処理順は無いが、1と2が終了次第、サービス3が行われる。
    Service1
    Service2 --> Service3

    サービス1とサービス2のいずれかが満たされれば次に進む。
    Service1 ---> Service3
    or
    Service2

    サービス1とサービス2が満たされない場合には次に進む。
    !Service1 --> Service3
    &&
    !Service2

    サービス1かサービス2のいずれかが満たされない場合に先に進む
    !Service1 --> Service4
    or
    !Service2

    まだあるかもしれないけど、ほろ酔い加減の頭ではここまでしか
    思いつかないよ。。。

    ここから見える事は、ここで書いた内容は【次の段階】へ進む為の条件である。
    class Service{
     Status getStatus();
            @nextCondition(COND_AND);
        Service next();
    }
    
    上記の内容は同じ様に戻る場合にも言えるはず。
    class Service{
     Status getStatus();
            
            @nextCondition(COND_AND);
        Service next();
    
            @backCondition(COND_OR);
            Service back();
    }
    

    以下は備忘。まだまとまってない。

    提供されるサービスは複数の書類を持つ。
    class Serivce{
    getDocument(String name)
    }

    書類には処理をする順番がある時がある。
    Doc1 --> Doc2 --> Doc3

    class Service{
    function Document getDocument(String name);

    }

    書類は明細を持つ場合、持たない場合がある。
    A Document doesn't have detail;
    A Document has a detail;
    A Document has many details;

    こんな感じか?

    @hasDetail(true)
    class Document{
    ...
    }

    2010年1月20日水曜日

    フレームワーク奮闘記 その1 Soil

    あけまして、おめでとうございます。
    今年はWebアプリケーションフレームワークを作る年になりそうです。
    最近は色んな優秀なフレームワークがありますが、自身でフレームワークを開発する
    機会に恵まれるとは思っていませんでした。というのも、現在の基盤が色々と
    問題を抱えているからで、改善!とか思ったのですが、修正箇所が
    膨れ上がってしまいそうなので、一層のこと0ベースでスタートしようかと
    言うのが事の始まりです。基本的な要件としては。。。
  • Java 1.5ベース





  • 開発者の効率が上がること





  • Connection系の処理は隠蔽する





  • SessionはService毎に付与すること





  • 必要なものを見極めてCacheしなさい





  • と何とも、何も決まっていない状況。
    白紙の地図を渡された状態なので、今から悶々とする日々が始まりそうです。
    全ての製品の土壌になることを目指して。。。
    Soilという名前だけは決めました。
    どう転んでいくのか、備忘の為に奮闘記をつけていこうと思います。