されたようですね。なんかちょっとペースが上がってきた?
ええ、もちろん、気になっていましたよ、Guice。
でも今まで触れてこなかったのには2つほど理由があります。
1. いそがしくて見る暇がなかった
2. 怖くて見るにみれなかった
しかし、今日後輩S君がMYCOMの記事
を見て、「LiQそっくりだ」とわざわざ指摘してくれるに及び、
ついに見てみぬふりできなくなりました。
思想的にねらっているところは、LiQとGuiceは全く同じだと思います。
じゃあ、実装で勝てるのか?というと、
まったく勝てる気がしないのですが。。
正直、へこんでます。
でも、自分の目指してきたのと同じ方向性のプロダクトが出てくることは、
喜ばしいことでもありますが。複雑な気分ですね。
勝てる気はしないとはいえ、LiQ Containerは一応いけるとこまで行きますよ!
ここまで作ってしまうと、さすがに自分で使うなら、隅々まで理解していて、自分で
責任とれるLiQ使います。だから、ちゃんと自分で使えるレベルに仕上げます。
最近忙しいし、もうサンプルアプリとか、いってらんないんで、
急いでBeta1リリースして、ドキュメントを書きます。
日本語で。
でも今まで触れてこなかったのには2つほど理由があります。
1. いそがしくて見る暇がなかった
2. 怖くて見るにみれなかった
しかし、今日後輩S君がMYCOMの記事
を見て、「LiQそっくりだ」とわざわざ指摘してくれるに及び、
ついに見てみぬふりできなくなりました。
思想的にねらっているところは、LiQとGuiceは全く同じだと思います。
じゃあ、実装で勝てるのか?というと、
まったく勝てる気がしないのですが。。
正直、へこんでます。
でも、自分の目指してきたのと同じ方向性のプロダクトが出てくることは、
喜ばしいことでもありますが。複雑な気分ですね。
勝てる気はしないとはいえ、LiQ Containerは一応いけるとこまで行きますよ!
ここまで作ってしまうと、さすがに自分で使うなら、隅々まで理解していて、自分で
責任とれるLiQ使います。だから、ちゃんと自分で使えるレベルに仕上げます。
最近忙しいし、もうサンプルアプリとか、いってらんないんで、
急いでBeta1リリースして、ドキュメントを書きます。
日本語で。
ちょっと仕事のからみでPHPをWindowsにインストールしようと
軽い気持ちではじめた作業でどっぷりとはまってしまいました。
なんでたかがインストールではまるんだー
悔しいですが、明日も仕事なので、今日はこれであきらめて帰宅。
なにが悪いんだろ? phpのモジュールはちゃんとロードされているのに。
phpがphpとして実行されません。。
情けない。
PHP 5.2.0
Apache 2.2.4
軽い気持ちではじめた作業でどっぷりとはまってしまいました。
なんでたかがインストールではまるんだー
悔しいですが、明日も仕事なので、今日はこれであきらめて帰宅。
なにが悪いんだろ? phpのモジュールはちゃんとロードされているのに。
phpがphpとして実行されません。。
情けない。
PHP 5.2.0
Apache 2.2.4
LiQ Containerのサンプルアプリで使おうと
思って、現在Click Frameworkを勉強中です。
思想はかなり近いので、両者の相性は良いはずです。
まだまだ知らないことも多いですが、ソース読んでみた印象はとても
良いですね。設計に奇をてらったところがなく、実に自然に
フレームワークの構造が頭に入ってきます。
中心となるクラスが5つくらいしかないので、全体を把握するのが容易
なのです。
ソースを読むことが本当に楽しい、そして多分、カスタマイズすることが
楽しいフレームワークだと感じました。やはり「理解できる」という安心感
は重要です。
なぜか最新のバージョン1.1がMavenのセントラルリポジトリにアップロード
されてないのが難点といえば難点。
思って、現在Click Frameworkを勉強中です。
思想はかなり近いので、両者の相性は良いはずです。
まだまだ知らないことも多いですが、ソース読んでみた印象はとても
良いですね。設計に奇をてらったところがなく、実に自然に
フレームワークの構造が頭に入ってきます。
中心となるクラスが5つくらいしかないので、全体を把握するのが容易
なのです。
ソースを読むことが本当に楽しい、そして多分、カスタマイズすることが
楽しいフレームワークだと感じました。やはり「理解できる」という安心感
は重要です。
なぜか最新のバージョン1.1がMavenのセントラルリポジトリにアップロード
されてないのが難点といえば難点。
リリースしました。
ダウンロードはこちらからどうぞ。
あいかわらずドキュメントが全然だったり、例外処理が手抜きだったりと
課題は山積ですが、今日だけは自画自賛させてください。
ほとんど全部のコードを書き直した結果、課題だった拡張性は大幅に
向上し、プログラムの構造もさらにシンプルに、きれいになりました。
いくつかのちょっと面白い新機能も盛りこまれています。
数寄者の方は是非ソースを読んでいただいて、批評して下さいませ。
例によって、ご意見、ご要望、批判、誹謗、中傷など歓迎します。
全体的なアーキテクチャはこれで大体Fixさせようと考えています。
なので、宣伝と、後でドキュメントを整備するときの叩き台とすること
を狙って、このblogでLiQ Containerの詳しい解説を
始めようかと思っています。
今後の予定は、beta1までの間に、ちょっとしたサンプルアプリを
作ってみて、足りてない機能がないかどうか検証します。
beta版は、public APIはFixして、ドキュメントの整備とバグフィックスを
行います。
段々自分の作ってるものに思い入れが出てきたので、是非
「使える」ものに仕上げていきたいとおもっております。
ダウンロードはこちらからどうぞ。
あいかわらずドキュメントが全然だったり、例外処理が手抜きだったりと
課題は山積ですが、今日だけは自画自賛させてください。
ほとんど全部のコードを書き直した結果、課題だった拡張性は大幅に
向上し、プログラムの構造もさらにシンプルに、きれいになりました。
いくつかのちょっと面白い新機能も盛りこまれています。
数寄者の方は是非ソースを読んでいただいて、批評して下さいませ。
例によって、ご意見、ご要望、批判、誹謗、中傷など歓迎します。
全体的なアーキテクチャはこれで大体Fixさせようと考えています。
なので、宣伝と、後でドキュメントを整備するときの叩き台とすること
を狙って、このblogでLiQ Containerの詳しい解説を
始めようかと思っています。
今後の予定は、beta1までの間に、ちょっとしたサンプルアプリを
作ってみて、足りてない機能がないかどうか検証します。
beta版は、public APIはFixして、ドキュメントの整備とバグフィックスを
行います。
段々自分の作ってるものに思い入れが出てきたので、是非
「使える」ものに仕上げていきたいとおもっております。
されたようです。ちょっと前の話みたいですが、なぜかJIRAの通知メールがGmailで
迷惑メールにされてて気づきませんでした。
いま、surefireのtrunkをおとしてきて動かしてみたら、確かに動き
ました。いままでは、JUnit4の、JUnit3のRunner用のアダプタ使っても、
パッチあてないと動かないような状態だったんですね。
これで@Testとかをちゃんと認識してテスト実行できるようになりました。
--
svn co http://svn.apache.org/repos/asf/maven/surefire/trunk/ surefire
--
とかで、最新のソースコード落としてきて、
--
mvn install
--
で使えるようになります。
迷惑メールにされてて気づきませんでした。
いま、surefireのtrunkをおとしてきて動かしてみたら、確かに動き
ました。いままでは、JUnit4の、JUnit3のRunner用のアダプタ使っても、
パッチあてないと動かないような状態だったんですね。
これで@Testとかをちゃんと認識してテスト実行できるようになりました。
--
svn co http://svn.apache.org/repos/asf/maven/surefire/trunk/ surefire
--
とかで、最新のソースコード落としてきて、
--
mvn install
--
で使えるようになります。
最近ブラックホール系のプロジェクトに飲み込まれているため、
あまり饒舌にはなれないですが、hiro345さんのエントリに
少々コメントをば。
さすがに鋭いご指摘だと思います。
JavaでDIの設定を書こう、という場合、環境依存の情報をどうやって扱うか、
というのは解決しなければいけない問題です。
違うマシンにデプロイするたびにソースコードからビルドしなおす
ようなことは当然許されるはずはないですから。
いまのところ、環境に依存した情報はModuleのsetter経由で
渡すことを考えています。
例えば、コネクションプールなどの機能をもつデータソースを
コンポーネントとして提供するモジュールであれば、
以下のようなイメージになります。
--
DataSourceModule module = new DataSourceModule();
module.setDriverUrl(...);
module.setUser(...);
module.setPassword(...);
module.setMaxConnections(..);
DataSource ds = module.getInstance(DataSource.class)
--
setterに渡す値はそれこそXMLなりプロパティファイル
なりから適当にとってくればいいと思います。
外部ファイルから設定をとってくるには既存のライブラリが
いろいろ使えると思ってるので、いまのところLiQ Container自身が
その仕組を提供することは考えていません。
ただ、関連プロダクトとしてそういうものを作る可能性はあります。
Moduleは限りなく
ふつうのJavaオブジェクトなので、XMLバインディングツールを
使ってモジュールをインスタンス化することすらできるはずです。
環境に依存する情報は、DIの設定からは切り離して、別途設定し、
DIの設定はプログラマのみがいじるようにすべきだと
思っています。
繰り返しになりますが、私がJavaで設定を書くべき、といっているのは、
DIに関してだけです。とくに運用の人にJavaコードで設定書かせるなんて
ひどいことはさすがに考えてないです。。
ところで、問題はこのモジュールが提供するDataSourceをよそのモジュールの
コンポーネントにどうやってInjectするか、なのですが、よくある
「継承」とかとはちょっと違うアプローチを
思い付いたので、alpha2で公開すべくがんばって作業してます。
alpha2は1月中のリリースが目標です。さすがにAPIはそろそろ安定
させたいものです。何をいってもやっぱり動くもの出してかないと
だめですしね、
力尽きたので、今日はこれまで。おやすみなさい。
あまり饒舌にはなれないですが、hiro345さんのエントリに
少々コメントをば。
さすがに鋭いご指摘だと思います。
JavaでDIの設定を書こう、という場合、環境依存の情報をどうやって扱うか、
というのは解決しなければいけない問題です。
違うマシンにデプロイするたびにソースコードからビルドしなおす
ようなことは当然許されるはずはないですから。
いまのところ、環境に依存した情報はModuleのsetter経由で
渡すことを考えています。
例えば、コネクションプールなどの機能をもつデータソースを
コンポーネントとして提供するモジュールであれば、
以下のようなイメージになります。
--
DataSourceModule module = new DataSourceModule();
module.setDriverUrl(...);
module.setUser(...);
module.setPassword(...);
module.setMaxConnections(..);
DataSource ds = module.getInstance(DataSource.class)
--
setterに渡す値はそれこそXMLなりプロパティファイル
なりから適当にとってくればいいと思います。
外部ファイルから設定をとってくるには既存のライブラリが
いろいろ使えると思ってるので、いまのところLiQ Container自身が
その仕組を提供することは考えていません。
ただ、関連プロダクトとしてそういうものを作る可能性はあります。
Moduleは限りなく
ふつうのJavaオブジェクトなので、XMLバインディングツールを
使ってモジュールをインスタンス化することすらできるはずです。
環境に依存する情報は、DIの設定からは切り離して、別途設定し、
DIの設定はプログラマのみがいじるようにすべきだと
思っています。
繰り返しになりますが、私がJavaで設定を書くべき、といっているのは、
DIに関してだけです。とくに運用の人にJavaコードで設定書かせるなんて
ひどいことはさすがに考えてないです。。
ところで、問題はこのモジュールが提供するDataSourceをよそのモジュールの
コンポーネントにどうやってInjectするか、なのですが、よくある
「継承」とかとはちょっと違うアプローチを
思い付いたので、alpha2で公開すべくがんばって作業してます。
alpha2は1月中のリリースが目標です。さすがにAPIはそろそろ安定
させたいものです。何をいってもやっぱり動くもの出してかないと
だめですしね、
力尽きたので、今日はこれまで。おやすみなさい。
昨日のエントリを書いたあと、やっぱりあまりにも
記述量が増えすぎるんじゃないかということと、コードの可読性が
かなり落ちてしまう、ということで思い直して、
今では、現在の記法も残そうと考えています。
型の安全性 vs 記述量と可読性というトレードオフの問題ですね。
Injectorのインタフェースは昨日の案の通り変更するつもりです。
特殊なInjectionをしたいときは昨日のコード例みたいな感じで書く
ことになります。匿名内部クラスの生成コード書くのはうっとおしい
ですが、IDEのコードテンプレートの機能とかをうまく使うと多少
マシになるのではないかと考えています。
ついでにInjectionのタイミングも、インスタンス生成直後に問答無用で
Injectしてしまうのではなくして、相互依存するコンポーネントを
setter injectionでinjectできるようにしたいと考えています。
そうすることによって、後々いろいろといいことがありそうなんです。
かなりの大手術になりますが。
記述量が増えすぎるんじゃないかということと、コードの可読性が
かなり落ちてしまう、ということで思い直して、
今では、現在の記法も残そうと考えています。
-- component(GlassBean.class).property("content") --
型の安全性 vs 記述量と可読性というトレードオフの問題ですね。
Injectorのインタフェースは昨日の案の通り変更するつもりです。
特殊なInjectionをしたいときは昨日のコード例みたいな感じで書く
ことになります。匿名内部クラスの生成コード書くのはうっとおしい
ですが、IDEのコードテンプレートの機能とかをうまく使うと多少
マシになるのではないかと考えています。
ついでにInjectionのタイミングも、インスタンス生成直後に問答無用で
Injectしてしまうのではなくして、相互依存するコンポーネントを
setter injectionでinjectできるようにしたいと考えています。
そうすることによって、後々いろいろといいことがありそうなんです。
かなりの大手術になりますが。
自分の書いたコードをオープンソースとして世間に公表したのは
この LiQ Contaienr がほぼ初めてですが、ポジティブなものであれ、ネガティブな
ものであれ、なんらかの反応がいただけるのは大変ありがたいことだと思います。
一つ一つのご意見が本当に参考になるし、自分のなかでまた新しい考えが
生まれてきます。
そして書きたいことがとても一つのエントリでは書ききれないほど
あふれてきます。
さて、いろいろなご意見にインスパイアされた結果、setter injection
の定義方法を次のようなイメージに変更しようという考えに至りました。
これで、プロパティを文字列で参照しなくてもよくなるし、
単なるsetter injection以外のいろいろなinjectionが一つの仕掛けで
実現できるようになります。
めちゃめちゃタイピング量増えてるじゃんか!
というおしかりはごもっともです。素直にあやまります。
ですが、私はもともと constructor injection派で、setter injectionは
本当にたまにしか使いません。
LiQ Containerも基本は constructor injectionが楽になるように作ってあります。
なので、setter 派の人には本当に申し訳ないのですが、
私的にはこれでもあんまり不満はないのです。
(とはいえ、本当はここでクロージャが欲しいところです。Dolphinで
クロージャが導入されることを期待してます)
むしろ、たまにしか使わない機能のための、めんどくさい introspection の
コードを一掃できてすっきりしますし、
何も削るものがないところまで無駄を省いて、緊張感を作り出す
というわび茶の精神にも合致します。
私が LiQ Container でやりたいのは、「DIコンテナの設定をJavaで書く」、
ということも確かにあるんですけど、「実はDIコンテナはもっと小さくても十分機能するのでは」
という仮説を検証することも同じくらい重要なのです。
最初の動機はJavaで設定書きたいっていうことだったんですけど、
LiQっていう名前を付けた瞬間から、実装をコンパクトにして、
必要最小限の機能だけをサポートする方向に大きく舵が切られましたね。
Javaで設定書いたほうがXMLとかで書くより実装を小さくできるという風に、
目的と手段がごっちゃになってしまった感じです。
最近、ライブラリとかフレームワークにとって重要なのは
十分にシンプルで、「理解できる」っていう安心感があることなんじゃないかと
思っています。「理解しがたい」フレームワークに依存することはプロジェクトにとってリスク
になると思います。
最初からそう考えてLiQを作りはじめたんではなくて、
LiQって名前つけて、シンプルなコンテナにしようと努力しはじめてからそう
考えるようになりました。
やっぱ名前重要です。
話は変わりますが、「設定が楽」だけではなく、「コンテナの使い方が簡単」
も実はアピールしたいポイントだったりします。
上の例の BeverageModule から、GlassBean.classのインスタンスを取り出すのは
以下のようにします。
自分では、この「設定をnew してすぐ使える」ってところが
意外に気に入ってるんですけどね。
Moduleになんかインターフェース実装させて、それ自体を他のModuleに
コンポーネントとして登録したりとか、簡単にできます。
この LiQ Contaienr がほぼ初めてですが、ポジティブなものであれ、ネガティブな
ものであれ、なんらかの反応がいただけるのは大変ありがたいことだと思います。
一つ一つのご意見が本当に参考になるし、自分のなかでまた新しい考えが
生まれてきます。
そして書きたいことがとても一つのエントリでは書ききれないほど
あふれてきます。
さて、いろいろなご意見にインスパイアされた結果、setter injection
の定義方法を次のようなイメージに変更しようという考えに至りました。
--- public void BeverageModule extends AbstractModule { public void moduleDef() { component(Water.class); component(GrassBean.class) .injector( new Injector<GrassBean>() { public void inject(GrassBean bean) { bean.setContent(using(Beverage.class)); } } ); } } ---
これで、プロパティを文字列で参照しなくてもよくなるし、
単なるsetter injection以外のいろいろなinjectionが一つの仕掛けで
実現できるようになります。
めちゃめちゃタイピング量増えてるじゃんか!
というおしかりはごもっともです。素直にあやまります。
ですが、私はもともと constructor injection派で、setter injectionは
本当にたまにしか使いません。
LiQ Containerも基本は constructor injectionが楽になるように作ってあります。
なので、setter 派の人には本当に申し訳ないのですが、
私的にはこれでもあんまり不満はないのです。
(とはいえ、本当はここでクロージャが欲しいところです。Dolphinで
クロージャが導入されることを期待してます)
むしろ、たまにしか使わない機能のための、めんどくさい introspection の
コードを一掃できてすっきりしますし、
何も削るものがないところまで無駄を省いて、緊張感を作り出す
というわび茶の精神にも合致します。
私が LiQ Container でやりたいのは、「DIコンテナの設定をJavaで書く」、
ということも確かにあるんですけど、「実はDIコンテナはもっと小さくても十分機能するのでは」
という仮説を検証することも同じくらい重要なのです。
最初の動機はJavaで設定書きたいっていうことだったんですけど、
LiQっていう名前を付けた瞬間から、実装をコンパクトにして、
必要最小限の機能だけをサポートする方向に大きく舵が切られましたね。
Javaで設定書いたほうがXMLとかで書くより実装を小さくできるという風に、
目的と手段がごっちゃになってしまった感じです。
最近、ライブラリとかフレームワークにとって重要なのは
十分にシンプルで、「理解できる」っていう安心感があることなんじゃないかと
思っています。「理解しがたい」フレームワークに依存することはプロジェクトにとってリスク
になると思います。
最初からそう考えてLiQを作りはじめたんではなくて、
LiQって名前つけて、シンプルなコンテナにしようと努力しはじめてからそう
考えるようになりました。
やっぱ名前重要です。
話は変わりますが、「設定が楽」だけではなく、「コンテナの使い方が簡単」
も実はアピールしたいポイントだったりします。
上の例の BeverageModule から、GlassBean.classのインスタンスを取り出すのは
以下のようにします。
--- BeverageModule module = new BeverageModule(); GrassBean bean = module.getInstance(GrassBean.class); ---
自分では、この「設定をnew してすぐ使える」ってところが
意外に気に入ってるんですけどね。
Moduleになんかインターフェース実装させて、それ自体を他のModuleに
コンポーネントとして登録したりとか、簡単にできます。
なぜか2chのSeasarスレにLiQ Containerの微妙な
フィードバックのようなものが。。。
>>341
LiQってAOPサポートしてないのか?
サポートしてません。今後も多分サポートしないでしょう。
以前AOP的な機能を実装してみたことがあるのですが、
仕様も実装も複雑になりすぎるので、泣きながら削除した、という経緯があります。
どうも私にはAOPというのはむずかしすぎるようです。
AOPをサポートするコンテナをお求めの方はS2かSpringをどうぞ。
>>348
この作者クラス名は文字列で書けねーのにプロパティ名は平気なのか?
平気なわけありません。凄く嫌です。でもこればっかりは
他にどうしようもないのではないでしょうか。
いろいろ考えたんですが、他に良いアイデアがでず。。
もう一ひねり欲しいな。
すいません。精進します。
ここで他のコンポーネントのプロパティを明示的に設定する方法が分かんね。
自分でコンポーネント取ってきてPropertyDependencyに食わせるのか?
moduleDef()の中でそんなことするわけねーか。
鋭い。。。
いまのところ、他のコンポーネントのプロパティを明示的にInjectする
方法は提供していません。これを実現するには自分でそういう
Dependencyを作る必要があります。
いくらシンプルが売りっていっても、このくらいはコアの機能として提供
しても罰はあたらないんじゃないかと思いますので、
alpha2には組み込む方向で考えたいと思います。
ちなみに、おっしゃる通りmoduleDef()のなかで自分でコンポーネントとってくるのは
反則です...
>>350
LiQClickとかLiQDaoとか予定あるんかな?
LiQ Containerの回りにそういう周辺フレームワークを作りたい気持ちは
大いにあります。
ちなみにまえLiQからS2Daoを使おうと試みたら、S2Frameworkが依存関係
としてくっついてきてしまうという事態が発生しました。
S2DaoをS2Frameworkに統合する計画があるようですが、分けて使いたい
人も少数ながらいる、ということも少し気にして欲しいですなぁ。
間違ってもKatsuraとかHamaなんて名前にはしないでくれよ
LiQの語源は離宮ではなく、利休なので、そのようなことには
ならないと思われます。
フィードバックのようなものが。。。
>>341
LiQってAOPサポートしてないのか?
サポートしてません。今後も多分サポートしないでしょう。
以前AOP的な機能を実装してみたことがあるのですが、
仕様も実装も複雑になりすぎるので、泣きながら削除した、という経緯があります。
どうも私にはAOPというのはむずかしすぎるようです。
AOPをサポートするコンテナをお求めの方はS2かSpringをどうぞ。
>>348
この作者クラス名は文字列で書けねーのにプロパティ名は平気なのか?
平気なわけありません。凄く嫌です。でもこればっかりは
他にどうしようもないのではないでしょうか。
いろいろ考えたんですが、他に良いアイデアがでず。。
もう一ひねり欲しいな。
すいません。精進します。
ここで他のコンポーネントのプロパティを明示的に設定する方法が分かんね。
自分でコンポーネント取ってきてPropertyDependencyに食わせるのか?
moduleDef()の中でそんなことするわけねーか。
鋭い。。。
いまのところ、他のコンポーネントのプロパティを明示的にInjectする
方法は提供していません。これを実現するには自分でそういう
Dependencyを作る必要があります。
いくらシンプルが売りっていっても、このくらいはコアの機能として提供
しても罰はあたらないんじゃないかと思いますので、
alpha2には組み込む方向で考えたいと思います。
ちなみに、おっしゃる通りmoduleDef()のなかで自分でコンポーネントとってくるのは
反則です...
>>350
LiQClickとかLiQDaoとか予定あるんかな?
LiQ Containerの回りにそういう周辺フレームワークを作りたい気持ちは
大いにあります。
ちなみにまえLiQからS2Daoを使おうと試みたら、S2Frameworkが依存関係
としてくっついてきてしまうという事態が発生しました。
S2DaoをS2Frameworkに統合する計画があるようですが、分けて使いたい
人も少数ながらいる、ということも少し気にして欲しいですなぁ。
間違ってもKatsuraとかHamaなんて名前にはしないでくれよ
LiQの語源は離宮ではなく、利休なので、そのようなことには
ならないと思われます。