Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
DIことはじめ- あなたのコードから new / if が消えます。魔法のDI -
都元ダイスケ
2009.3.14 Seasar Conference 2009 White
自己紹介
都元ダイスケ
http://d.hatena.ne.jp/daisuke-m
Jiemamy Project チーフコミッタ
DBの設計管理の敷居を下げるSeasar Project Doltengコミッタ
ゴメンナサイ ゴメンナサイ
Works
http://www.atmarkit.co.jp/fdb/single/08s_jiemamy/jiemamy1.html
Agendaイントロ ~ 基礎知識の整理
依存性について
仕様と実装
いつDIが欲しくなるのか
Seasar2の基礎の基礎
ちょっとした応用
今日はDIのお話
DI = Dependency Injection = 依存性注入
依存性を注入すること
そのメカニズムのこと
まずはDIは置いておき、基礎知識の整理を。
Section 1イントロ ~ 基礎知識の整理
依存性って?
自動車 → エンジン
エンジン → ガソリン
書籍 → 文字
iPod → Mac or PC
ソフトウェア → ハードウェア
A → B
AはBがあって初めて動作する・意味を成す。
AはBがなければ動かない・意味がない。
Javaで言うと「AクラスがなければBクラスがコンパイルできない」のが依存。
クラス同士の依存
Appクラスは、StringBuilder, String, Systemクラスに依存。
依存は少ない方がいい
例えば StringBuilder#append(String)メソッドが廃止された!?
その途端、Appクラスは動かない
コンパイルさえ出来ない
依存性があると、依存先クラスの変更時に依存クラスに影響が出る
抽象的なもの (abstract)依存は、より抽象的なものに対して
抽象的 ←→ 具体的
ある乗り物の作成時…
「燃料」に依存する乗り物を作る
当初はレギュラーだったものが固形燃料に変わっても、その乗り物に影響はない。
「ハイオク」に依存する乗り物を作る
レギュラーになっただけで、乗り物の作りを変える必要あり。
どちらが望ましい?
クラスよりもインターフェイスの方がより抽象的
仕様と実装仕様の例
fooメソッドの結果、"Miyamoto Daisuke" という文字列が表示される
その実装の例
先ほどのStringBuilderのコードSystem.out.println("Miyamoto Daisuke");
StringBuilderに依存しない実装
実装ではなく仕様に依存(1)
自動車 → エンジン ですが、幸いV型4気筒DOHCエンジンには依存していない
ハイブリッドエンジンでも車は動く自動車 uses エンジンV型4気筒DOHCエンジン implements エンジンハイブリッドエンジン implements エンジン
つまり、インターフェイスだけで、その実装クラスが無くてもコンパイルできるように。
interfaceを使うと、仕様と実装が分離でき、実装に依存しないコードを書く事ができます…?
実装ではなく仕様に依存(2)
実装ではなく仕様に依存(3)
Section 2いつDIが欲しくなるのか
そろそろお題を
求める結果
CREATE TABLE T_USER ( ID INTEGER, USERNAME VARCHAR(32), PASSWORD VARCHAR(32));
最低限の要求を満たすコード
Main
BusinessLogic
Converter
ここで仕様変更ですよOracleにも対応してくれんかね。INTEGER → NUMBERVARCHAR → VARCHAR2
もちろん、今までの変換もできるようにね。
依存性の切り離し現在 BL は Converter の実装に依存
仕様(=interface)に依存するように変更を加える
public class OriginalConverter implements Converterpublic class OracleConverter implements Converter
Oracleに対応INTEGER → NUMBERVARCHAR(32) → VARCHAR2(32)
これでBLはConverter実装無しでコンパイルができる…?
じゃあさ、
Mainが_________を入手した時既に_________のインスタンスが______フィールドに入ってればいいんじゃない?
これがDIというものらしい
BusinessLogicConverter実装
converter
Dependency
Injection
Section 3Seasar2の基礎の基礎
Seasar2を使うと…
(参考:さっきのコード)
新しいBusinessLogic
これで、Main, BusinessLogic共にConverter実装が無くてもコンパイルできるようになりました。
何が起きたのか?BusinessLogicをnewする時には、コンストラクタに何らかのConverterを与えなければならない
Seasar2は、BusinessLogicのインスタンスをどのようにして作ったのか…?
(コードから、BLのnewが消えています。)
diconファイル (S2の設定ファイル)
BusinessLogicを "businessLogic"と命名
そのコンストラクタ引数(arg)には、OriginalConverterをあげてくださいね。
classpathルートの app.dicon
DIを使うとどうなるか
コンパイル時に、依存の実装が要らなくなる
実行時(ランタイム)のみ、実装が要る
再コンパイルなしで、XML(dicon)を書き換え
るだけで、プログラムの動作を変えられる
XML書き換え
DB選択のifが消えました
DIコンテナ - S2Container
コンポーネント(=インスタンス)の管理人
くれ(getComponent)といったらくれる
しかも、依存性を解決してくれる
インスタンスのライフサイクル管理
いつ生成され、いつ破棄されるのか
DIの種類コンストラクタ・インジェクション先ほどの例
セッター・インジェクションnew後、setterを介してインジェクション
メソッド・インジェクションnew後、任意のメソッドを実行
フィールド・インジェクションフィールドに直接インジェクション
Section 4ちょっとした応用
実はdiconはコレでもいい(実装が1種類しか無い時限定)
2つのコンポーネント(インスタンス)が登録された状態
これだけで、getComponent("businessLogic") する。
この時、S2の脳内では…BusinessLogicくれって言われた。
でもコンストラクタにConverterが要る。
俺、Converter型のコンポーネント、何か持ってたっけ…?
あ、OracleConverterがあった。
こいつ食わせとくか。
自動インジェクションと、呼ばれている機能です。
もの凄く、空気読んでくれる系。
ただし、自動DIには細かい条件アリ
トラブル
なぜかインジェクションされない
なぜかインジェクションされてしまう
ドキュメント必読
まとめDIは、オブジェクト指向の理論の上にある依存性は小さく & 出来る限り抽象(仕様)に依存
Seasar2は、DIを実現する仕組み主要な型は S2Container依存定義はdiconファイルに記述 (app.dicon)自動インジェクション等の機能もアリ
実はStrategyパターン
以上、ご清聴ありがとうございました。