«前の日記(2005-06-01(Wed)) 最新 次の日記(2005-06-03(Fri))» 編集
RSS feed
Webサイトとは「つい、うっかりの存在論」である

角谷HTML化計画

「むずかしく考えることはない」と、偉そうに葉巻を振りまわしながら、トレヴィラヌスはいった。「ガリラヤの太守がじつにみごとなサファイアを持っていることは、みんなが知っている。何者かがそれを盗むつもりで、間違ってここへ入ったんだ。ヤルモリンスキーが起きていたので、泥棒は殺さざるをえなかった。どうだね、これで?」
「そのとおりかもしれません。しかし、おもしろくはないですね」と、レンロットは答えた。
J.L.ボルヘス『死とコンパス』(『伝奇集』収録)

2005-06-02(Thu) [長年日記]

■1 車輪の再実装: 簡易DIコンテナ on Groovy

Groovyで、クラスの数が10〜15程度の規模で書かれたコードをDRY原則に従ってリファクタしていると、EoT(Ease of Testing:テスト容易性)の観点からDIコンテナが欲しくなってきた。

しかし、この規模のコードではSeasar2はおろか、PicoContainerですらヘビーウェイト。なので、id:t-wadaさんとTDD && ペアプロで作成してみた。

機能としてはAOPもXMLによる設定も無く、オブジェクトのwiringだけだが、我われの現在の用途には必要十分。インジェクション方法は、ブロック・インジェクション——Groovyだからクロージャ・インジェクションと呼ぶべきか——のみをサポート。車輪の再実装は善。って、『Linux mgazine』(2005.02)のMatzダイコンを丸パクリなので、再実装ですらないか。

利用イメージ

こんな感じ:

class Blog {
  input
  display
  ...
}

class Input {...}

...

dicon = new DICon()
dicon.regist("blog") {|c| new Blog(input:c.input(), display:c.display)}
dicon.regist("input") {|c| new Input()}
dicon.regist("display") {|c| new Display()}

blog = dicon.blog # dicon.blog() でも良い
blog.display...

テストコード

ガリガリ書き流したので安直だったりコピペだったりで手抜き。「Code as Documentation」になってない。

1  package com.kakutani.groovy.di
2
3  class DIConTest extends GroovyTestCase {
4    dicon
5
6    void setUp() {
7      dicon = new DICon()
8    }
9
10    void testOneCompoent() {
11      dicon.regist("myString") { "Hello World" }
12      assertEquals("Hello World", dicon.myString)
13    }
14
15    void testTwoCompoent() {
16      dicon.regist("myString") { "Hello World" }
17      dicon.regist("foo") { "Hello Foo" }
18      assertEquals("Hello Foo", dicon.foo)
19    }
20
21    void testDependency() {
22      dicon.regist("lineItem") { "ThinkPad"}
23      dicon.regist("order") {|c|
24        order = []
25        order[0] = c.instance("lineItem")
26        order
27      }
28
29      assertEquals("ThinkPad", dicon.instance("order")[0])
30    }
31
32    void testPropertyMissing() {
33      dicon.regist("lineItem") { "ThinkPad" }
34      dicon.regist("order") {|c|
35        order = []
36        order[0] = c.lineItem
37        order
38      }
39
40      assertEquals("ThinkPad", dicon.order[0])
41    }
42
43    void testMethodMissing() {
44      dicon.regist("lineItem") { "ThinkPad" }
45      dicon.regist("order") {|c|
46        order = []
47        order[0] = c.lineItem()
48        order
49      }
50
51      assertEquals("ThinkPad", dicon.order()[0])
52    }
53 }

プロダクトコード

Classic Syntax。JSR Syntaxは気にくわない、というのもあるけれど、MarkupとBuilderが使えないと困るので、beta10を採用。

行数は39行。所要時間は、mixiの日記のタイムスタンプから算出すると29分。getPropertyとinvokeMethodのオーバーライドでハマった(自分で翻訳していたというのに)。メソッドの仮引数の型を明示しないとオーバーライドできないのね……。

ちなみに、ブロック・インジェクションなMatzダイコンはRubyで20行。

1  package com.kakutani.groovy.di
2
3  class DICon {
4    instances
5    services
6
7    DICon() {
8      instances = [:]
9      services = [:]
10    }
11
12    DICon regist(name, closure) {
13      services[name] = closure
14      this
15    }
16
17    Object instance(name) {
18      if (instances[name] != null) return instances[name]
19      closure = services[name]
20      component = closure.call(this)
21      instances[name] = component
22    }
23
24    getProperty(String name) {
25      try {
26        return metaClass.getProperty(this, name)
27      } catch(MissingPropertyException e) {
28        return instance(name)
29      }
30    }
31
32    invokeMethod(String name, Object args) {
33      try {
34        return metaClass.invokeMethod(this, name, args)
35      } catch(MissingMethodException e) {
36        return instance(name)
37      }
38    }
39  }

さらに先に進むために

GroovyでAOPというかインターセプターというか、そーゆうのを仕込もうと思ったらどういうやり方があるのかなあ……。AspectGとか無いのかな。

■2 TodoListTutorial with Rails

id:babieさんによる翻訳。お疲れさまでしたッ!

本日のツッコミ(全3件) [ツッコミを入れる]
babie (2005-06-03(Fri) 23:51)

ども。実は、このチュートリアル、原文のコード見るだけでも、十分わかりやすいんですけどねw。

TrackBack (2005-06-07(Tue) 07:16)

http://d.hatena.ne.jp/Kazzz/20050607/p1<br>Kazzの「JとNの狭間で」<br>[Java]LightWeight DIContainer on Groovy<br> [http://www.kakutani.com/20050602.html#p01:title] Javaではなく正確にはGroovyなのだけれどDIコンテナを実装してみました、というお話し。 私が知っている中では最軽量のDIコンテナと思います。 AOPもXMLによる設定も無く、オブジェクトのwiringだけなのだそうだけど..

TrackBack (2005-06-21(Tue) 23:40)

http://kakutani.com/20050621.html#p02<br>角谷HTML化計画<br>車輪の再実装: 簡易DIコンテナ on Groovy with AOP<br>今度はGroovyダイコンに簡易AOP機能を実装してみた。コンテナ部分のコードは45行増えて84行に。


«前の日記(2005-06-01(Wed)) 最新 次の日記(2005-06-03(Fri))» 編集
RSS feed