過去の日記

2006-02-07 DIコンテナ? [長年日記]

なんで new List(); か? [tech]

もしそんなことができるとしたら、あるいはできるようにするとしたら、どうなるのだろうか? と考えて楽しんでいるだけなんですがね。

DIコンテナって [tech]

明確な仕様を持ち、異なる実装(異なるコンテナ)間での可搬性を獲得した、factory methodパターンの1実装?
……いやいやそれだけだとInversion of Controlという別名が示す、旧EJBコンテナとの対立概念であるという表明を明確に説明しない。
あー、対立概念ではないのか?
旧EJBコンテナもまたDIコンテナの1実装であって、つまり古い「コンテナ」という概念よりも広いアーキテクトとして Dependency Injectionコンテナという概念がでてきたのかな。
うーん。勉強不足。

変数の動きを脳内で追ってみよう(短期記憶の強化にいいかも?) [etc]

ズバリ当てられなかった。どこかで計算間違えたらしい。
途中で挫折するほど大変ではないが、ちゃんと当てられるほど簡単ではない。

頭の中で一体何をやっているのだろうか…と問いただしたくなる。例えば変数を3つ使って行う作業を頭の中で行おうとしたら、最低でも3つのことを同時に、しかも正確に覚えていなければならない。そんなことができる人間がこの世に何人いるのだろうか…例えば、以下のプログラム。

 1 a := 1;
 2 b := 3;
 3 c := 6;
 4 a := a+b;
 5 c := c+b-a;
(引用 略)
17 a := (c+5)/(a-2);
18 b := (a+c)/b;
19 c := (c/b)+1;
20 a := c/a

「:=」は代入を表す。…さて、このプログラムは必ず不正終了する。実際にこのスクリプトを組まず、メモも一切取らず、ただこのコードを眺めるだけで(これがルール)、何行目の処理でエラーが発生しているかをズバリ当ててみて欲しい。

Hatena::Diary::排他的論理和雑記 - 正しくないかもしれない、間違ってるかもしれない


どうでもいいけど := が代入だからPascalで、と思ったら / を div に変えないといけなかった……。: を削って ruby か perl で実行する方が楽。

トラックバックがおかしい [hatena]

わんこ日記さんのところでも指摘があったけど、確かにはてなへのトラックバックがおかしいみたいだ。

was not hatena-group. (TDiary::TDiaryTrackBackError)


ってことで、hatenaにはじかれてしまった。hatenaからでないとトラックパックできないのかなぁ?

わんこ日記(2006-02-11)


追記
復旧したみたいだけど……、しまった。テストのために自動トラックバックを設定したのをそのままにしてた。

アノテーションでは「空気の様に」とはいかないか [tech]

↓(new List();を再度考えるのエントリ)の様なことを考えると、injectionする対象を絞り込みたいわけで、DIのためのアノテーションを文法に入れた方がよくなって「空気の様に」とはいかないかなぁ。

if (hoge) {
  List items = new List();
}
else {
  List items = new List();
}

は、変数としてのitemsはスコープが分離しているので文法上okだけど、DIのための識別子としてはうまくない。
いや、変数としては別だけどDIとしての識別子は同じになる、という扱いにするか。それもなんとなく気持ち悪い。……じゃなくてやっぱり「空気の様に」とはいかないということか。

new List();を再度考える [tech]

結城さんにも取り上げられたみたいだし、再度考えてみる。

List items = new List();
(略)
ランタイム時にnew List()の実装クラスを解決するわけだが、おそらく設定ファイルの類になる。すると規模が大きいと定義の数が増えて面倒だ。そこで、interface List内にアノテーション等でデフォルトの実装クラス(参照実装ともいえるかな)は何だという定義を埋め込んでおけばよい。すると、new List()のデフォルトはnew ArrayList()となり、もし違う実装クラスに変更したければ、設定ファイル等でオーバーライドすればよい。

ナンセンス不定記


現状ではどうするか? を考えてみよう。
ソースを書いている時点で、規模や使われ方が想像できなくてさてどんな実装にするか? と迷ったとして、

List items = new ArrayList();  //Todo

とか、

List items = new LinkedList();  //Todo

なんて書いておくんだ。
後々ソースができあがってくると、addとiteratorが使えれば十分と判ったり、get()が頻繁に必要だと判ったりする。
それで生成するものを変えたり、場合によっては List で定義されたメソッドではなくて実装しているクラスの方のメソッドを使うべきと判断したら、

ArrayList items = new ArrayList();

と書き直したりする。

あるいは、実際に動かしてみたり、運用のフェーズに入って、このitemsが何件ぐらいになるのか? の目星がついたりしたら、

List items = new ArrayList(50);  //Todo

とか書き直したりする。


問題は、運用に入った後でget()が多くてLinkedListじゃ駄目だった! とか、itemsの見積もりが甘くて、ここは new ArrayList(100); が妥当だった! とか気がついてもソースを直すしかないってこと。

ま、この時点でプログラマとして失格、という感じがなきにしもあらずだけど、"とりあえず"で書いておいたコードがほったらかしになってました、とか言語の理解が浅かった新人に書かせた部分がまずかった、とか。

そんなことは……往々にしてあるなぁ。


で、

List items = new List();

の登場。
DIコンテナの本来の意図からは外れるとは判った上で書くけど、このclassのこのmethod内でのnew List() は、new LinkedList()を生成しろ! と後から指定できるのはいいかも。
でもなんか後ろ向き……。


ここまで書いてきてもひとつ思いついたのは、このitemsにどのぐらいの要素が入るか? とかハッキリしない状態で書かざるを得ないケース。その時に運用テストの段階(かそのもう一つ直前の段階)で、プロファイルを取るようなArrayListのサブクラスで動かしてみて確認して、本番ではそのプロファイルからはじき出した初期値でのインスタンス生成 new ArrayList(int) で動かすとか。


現時点では、こういうのをやるには――それが必要だと判っている局面であれば―― factory mthodパターンなどを自分で作り込む必要があったわけだ。
それが言語仕様のレベルでサポートされる、というのはつまり「factory mthodパターンを自分で書く必要が無くなる」というだけの話?


ありゃ、

prima materia - laboratory

で考えたことに話が戻っただけか。

DIコンテナという呼び方よりも、「言語仕様のレベルでサポートされる factory method」かしら。それとも、それこそがDIコンテナの本質?

不勉強さが露わになっただけだったか……。