Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
DI(依存性注入について)
Search
yuizho
November 21, 2015
Programming
520
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
DI(依存性注入について)
yuizho
November 21, 2015
More Decks by yuizho
See All by yuizho
サーバ構築を自動化する~Ansible ~
yuizho
1
130
Other Decks in Programming
See All in Programming
Go 1.27からのGODEBUG / Go 1.27 リリースパーティ #go127party
mazrean
0
320
iOS開発×AI駆動開発 〜最近使って便利だったスキルの話〜
nogu66
0
140
書籍「プロフェッショナルAI駆動開発」紹介スライド
juntaromatsumoto
0
990
DroidKaigi 2026 「個人開発という実験場: Android エンジニアが手にする4つの自由」
slashnephy
0
220
片田舎のおっさん、 Swift Buildのダイアモンド問題解決の不具合修正PRを出すが、解決方法がキャッシュをしないようにすることであり、ビルド時間が伸びると言われてマージされないので高速化もする/swiftbuild
yimajo
0
360
私のClaude Code活用法 (個人開発編) - PHPerKaigi mini #4(2026/08/24)
panda_program
1
210
新人はどこまで自力でやり、どこからAIに頼るべきか/エンジニア育成に向き合う_先輩たちの悩みと知見共有会
toppan_digital_dev
1
560
業務時間外もAIに働いてもらう話
colorful12
3
10k
FastAPI の並行処理モデルを完全に理解する
hoto17296
9
3.8k
PyConJP2026_wat_Python × Signal Processing: How to Draw Pictures with Sound Using Spectrogram Art
wat
0
670
{ Android | Kotlin } Gradle Plugin in 2026
ryunen344
1
290
Snowflakeで業務アプリを作ろう。 Snowflakeのアプリ機能解説&実践ガイド
ayumu_yamaguchi
1
110
Featured
See All Featured
YesSQL, Process and Tooling at Scale
rocio
174
15k
The browser strikes back
jonoalderson
0
1.6k
Making Projects Easy
brettharned
120
6.7k
We Are The Robots
honzajavorek
0
340
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
510
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.2k
Building an army of robots
kneath
306
46k
How to train your dragon (web standard)
notwaldorf
97
6.8k
Scaling GitHub
holman
464
140k
The State of eCommerce SEO: How to Win in Today's Products SERPs - #SEOweek
aleyda
2
11k
The Impact of AI in SEO - AI Overviews June 2024 Edition
aleyda
6
1.2k
AI: The stuff that nobody shows you
jnunemaker
PRO
9
970
Transcript
DI(依存性注入)について 伊藤 結
ところで、DIと聞いて ピンとくる方はいますか?
DI(依存性注入)とは なるほど。わからん。 依存性の注入(英: Dependency injection)とは、コンポーネント間の依存関係をプロ グラムのソースコードから 排除し、外部の設定ファイルなどで注入できるようにするソ フトウェアパターンである。英語の頭文字からDIと略される。 wikipediaより https://ja.wikipedia.org/wiki/依存性の注入
DI(依存性注入)とは 依存性の注入(英: Dependency injection)とは、コンポーネント間の依存関係をプロ グラムのソースコードから 排除し、外部の設定ファイルなどで注入できるようにするソ フトウェアパターンである。英語の頭文字からDIと略される。 wikipediaより https://ja.wikipedia.org/wiki/依存性の注入 言葉の意味から考えてみよう!
依存性ってなに?
public class Siphon implements BrewingMethod { @Override public String brew()
{ return "サイフォンでいれたコーヒー "; } } public class CoffeeShop { public String brewCoffee() { BrewingMethod siphone = new Siphone(); return siphone.brew() + "が出来上がりました [_]P"; } } public class CoffeeShopApp { public static void main(String... args) { CoffeeShop coffeeShop = new CoffeeShopApp(); System.out.println(coffeeShop.brewCoffee()); } }
public class Siphon implements BrewingMethod { @Override public String brew()
{ return "サイフォンでいれたコーヒー "; } } public class CoffeeShop { public String brewCoffee() { BrewingMethod siphone = new Siphone(); return siphone.brew() + "が出来上がりました [_]P"; } } public class CoffeeShopApp { public static void main(String... args) { CoffeeShop coffeeShop = new CoffeeShopApp(); System.out.println(coffeeShop.brewCoffee()); } } プログラムの実行クラス BrewingMethod(抽出方法) の実装クラス
クラスAからクラスBを直接インスタンス化している時、 クラスAはクラスBがないと動きません。 このような状態は クラスAとクラスBが依存関係にある、 クラスAはクラスBに依存しているといえます。 今回の例でいうと、 CfeeShopAppとCoffeeShop CoffeeShopとSiphone の間で依存関係があるということになります
注入ってなに?
実際のコードで説明します
DIコンテナを使って、 実際にDIをやってみよう!
DIコンテナとは • すごく簡単に言うと、「XXにこのクラスのオブジェクトを注入してね」 という設定を書いておくとDI(依存性の注入)を実行するよくんのこと。 今回はJava向けのDaggerというDIコンテナを使います。
@Module(injects = CoffeeShopApp.class) public class BrewingMethodModule { @Provides public BrewingMethod
provideBrewingMethod() { return new Siphon(); } } public class CoffeeShop { // Siphonオブジェクトが注入される @Inject BrewingMethod brewingMethod; .... } public class CoffeeShopApp { //兄弟クラスがないので設定なしで CoffeeShopオブジェクトが注入される @Inject CoffeeShop coffeeShop; public void run() { System.out.println(coffeeShop.brewCoffee()); } public static void main(String... args) { // Daggerのオブジェクト生成(設定を読み込んで、各オブジェクトが注入された CoffeeShopAppオブジェクトを生成) ObjectGraph objectGraph = ObjectGraph.create(new BrewingMethodModule()); CoffeeShopApp coffeeShopApp = objectGraph.get(CoffeeShopApp.class); coffeeShopApp.run(); }
@Module(injects = CoffeeShopApp.class) public class BrewingMethodModule { @Provides public BrewingMethod
provideBrewingMethod() { return new Siphon(); } } public class CoffeeShop { // Siphonオブジェクトが注入される @Inject BrewingMethod brewingMethod; .... } public class CoffeeShopApp { //兄弟クラスがないので設定なしで CoffeeShopオブジェクトが注入される @Inject CoffeeShop coffeeShop; public void run() { System.out.println(coffeeShop.brewCoffee()); } public static void main(String... args) { // Daggerのオブジェクト生成(設定を読み込んで、各オブジェクトが注入された CoffeeShopAppオブジェクトを生成) ObjectGraph objectGraph = ObjectGraph.create(new BrewingMethodModule()); CoffeeShopApp coffeeShopApp = objectGraph.get(CoffeeShopApp.class); coffeeShopApp.run(); } @Moduleで注入先クラスを指定 @Providesを付与したメソッドで、注入するオ ブジェクトを生成する処理を記述。 Daggerライブラリのオブジェクト生成処理 (BrewingMethodModuleの設定を読み込 んで、CoffeeShopAppオブジェクトを生 成)。 @Injectが付与されている CofeeShopApp#cofeeShop, CofeeShop#resingMethod にオブジェクトが注入された状態の CoffeeShopAppオブジェクトが生成されま す。
Daggerが依存性が注入されたオブジェクトを生成することで、 CofeeShopAppから直接インスタンス化する記述をなくすことができ、 以下のモジュール間の依存関係を外部に逃がすことができました。 CofeeShop ー Siphon CoffeeShopApp ー CofeeShop
で、DI使うと なにがよくなるの?
DIを使う場合の利点 • モジュール間の依存関係を弱めることができる (保守性が高まる) • 単体テストが楽になる (Aモジュールが完成する前にBモジュールをテストできる、外から特定のモジュールをモック に差し替えることができる) 実際やってみて、特にテストコードを書くとき、Mockオブ ジェクトに差し替えてテストながせるのが心地よかったで
す。
public class CoffeeShopTest { @Inject CoffeeShop coffeeShop; @Inject BrewingMethod brewingMethod;
@Before public void setUp() { ObjectGraph.create(new TestModule()).inject(this); } @Module(includes = BrewingMethodModule.class, injects = CoffeeShopTest.class, overrides = true) static class TestModule { @Provides @Singleton public BrewingMethod provideBrewingMethod() { return Mockito.mock(BrewingMethod.class); } } @Test public void testBrewCoffee() { Mockito.when(brewingMethod.brew()).thenReturn("テストコーヒー"); String result = coffeeShop.brewCoffee(); Mockito.verify(brewingMethod, Mockito.times(1)).brew(); assertThat(result, is("テストコーヒーが出来上がりました [_]P")); } DIを利用したテストコードの一例 CoffeShopのテストコードです。 BrewingMethodクラスのオブジェクトは モックに置き換えてテストを実行してい ます。 CoffeeShopから BrewingMethod#brewメソッドが1回呼 ばれていること、 CoffeeShop#brewCoffeeメソッドの結 果が正しいこと を確認するテストコードです。
public class CoffeeShopTest { @Inject CoffeeShop coffeeShop; @Inject BrewingMethod brewingMethod;
@Before public void setUp() { ObjectGraph.create(new TestModule()).inject(this); } @Module(includes = BrewingMethodModule.class, injects = CoffeeShopTest.class, overrides = true) static class TestModule { @Provides @Singleton public BrewingMethod provideBrewingMethod() { return Mockito.mock(BrewingMethod.class); } } @Test public void testBrewCoffee() { Mockito.when(brewingMethod.brew()).thenReturn("テストコーヒー"); String result = coffeeShop.brewCoffee(); Mockito.verify(brewingMethod, Mockito.times(1)).brew(); assertThat(result, is("テストコーヒーが出来上がりました [_]P")); } BrewingMethodModuleを、BrewingMethod のモックを返却するように上書きしている。
public class CoffeeShopTest { @Inject CoffeeShop coffeeShop; @Inject BrewingMethod brewingMethod;
@Before public void setUp() { ObjectGraph.create(new TestModule()).inject(this); } @Module(includes = BrewingMethodModule.class, injects = CoffeeShopTest.class, overrides = true) static class TestModule { @Provides @Singleton public BrewingMethod provideBrewingMethod() { return Mockito.mock(BrewingMethod.class); } } @Test public void testBrewCoffee() { Mockito.when(brewingMethod.brew()).thenReturn("テストコーヒー"); String result = coffeeShop.brewCoffee(); Mockito.verify(brewingMethod, Mockito.times(1)).brew(); assertThat(result, is("テストコーヒーが出来上がりました [_]P")); } 本クラスへの依存性注入の実行 CoffeeShop#brewingMethod、 brewingMethodへ BrewingMethodのMockを注入する。 (TestModule#provideBrewingMethodに Singletonアノテーションを付与しているので すべて同じオブジェクトが注入される)。 注入した、モックオブジェクトの振る舞 いを設定して、テストを実行。 ※BrewingMethod#brew()が呼ばれ た際に”テストコーヒー”が返却されるよ う設定。
DIコンテナって 他にはどんなのがあるの?
代表的なDIコンテナ • Spring Framework • JavaEE (CDI) • Seasar2 •
Zend Framework 2 • Dagger • Dagger2 • Proton • RoboGuice
なんかJavaばっかりじゃね?
言語とDIコンテナ • Javaなどの静的言語では色々と種類があるが、 RubyやPythonなどの動的言語ではあまり使われていない (と思う)。 私は一時DIについて関心を持って、いろいろ調べてみたし、 自分でDIコンテナ を実装してみたりもした。 でも、RubyでならDIコンテナがわずか20行で記述で きる上、
よく考えてみたら、その20行も、なくてもほぼ同じことが簡単に実現で きることに気がついた時、 DIってのは硬直した言語のための技術なんだと気 がついた。 Matzにっき より http://www.rubyist.net/~matz/20091003.html
どんな所でDIを使うべき?
DIの使いどころ • (当たり前ですが) DIを前提にしたフレームワークを使用するとき。 • Javaを使用しており、テスト駆動開発 (TDD)とかテストコードを書くことが前提のプロジェクト。 • 実装があるモジュールに依存してるが、そのモジュールは未完成、でも単体テストを始めない といけないんだよ〜みたいなことになりそうなとき。
採用したときのコスト(学習コストなど)に比べて、モ ジュール間の依存関係を弱めることが重要な時に使用 するべき。 何でもかんでもDIすればいいってもんでもない。
ご清聴ありがとうございました