Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Dependency Injectionとは

957 views

Published on

依存・インターフェイス・依存注入について
お勉強。

Published in: Engineering
  • Be the first to comment

  • Be the first to like this

Dependency Injectionとは

  1. 1. Dependency Injectionとは doi
  2. 2. 依存とは Dependency
  3. 3. 依存とは • 僕はパソコンが無いと生きていけない • 僕はパソコンに依存 • ネットがないと僕は生きていけない • 僕はネットとパソコンが無いと
 成立しない状態
  4. 4. 例えば
  5. 5. Code class Enemy { int hp; public void damage(int damage) { hp -= damage; } } class Boss { int hp; public void damage(int damage) { hp -= damage; } } class Player { public void attackEnemy(Enemy enemy) { enemy.damage( 10 ); } public void attackBoss (Boss boss) { boss.damage( 10 ); } }
  6. 6. Code class GameManager { Player player; Enemy enemy; Boss boss; public void start() // ゲーム開始時に一度だけ呼ばれる { player = new Player(); enemy = new Enemy(); boss = new Boss(); } public void update() { if (KeyDown( A_BUTTON )) // Aボタンが押されていたら player.attackEnemy( enemy ); if (KeyDown( B_BUTTON )) // Aボタンが押されていたら player.attackBoss( boss ); } }
  7. 7. クラス図 Player は Enemy と Boss に依存してる
  8. 8. 依存の影響
  9. 9. Open-Closed Principle オープン・クローズドの原則
  10. 10. 敵を増やそう マジシャン、狂熊、ワルガキ 凶悪でかっこいいモンスターのアイデアがじゃぶじゃぶ湧き出る…!!
  11. 11. Code class Player { public void attackEnemy(Enemy enemy) { enemy.damage( 10 ); } public void attackBoss(Boss boss) { boss.damage( 10 ); } public void attackMagician(Magician magician) { magician.damage( 10 ); } public void attackWarBear(WarBear warBear) { warBear.damage( 10 ); } public void attackBadBoy(BadBoy badBoy) { badBoy.damage( 10 ); } }
  12. 12. クラス図 Player はいろんな敵を
 知っている状態じゃないと成立しない
  13. 13. 依存を減らしたい • Playerの他者への依存は膨らむばかり • 依存をなんとか減らせないか
  14. 14. 共通のインターフェイス • クラスの持つべき性質をルール化する • 基底クラス • C# の interface, C++なら多重継承 • Duck Typing • ルールを決める手段は言語や処理系によって様々 • ルール:ダメージを受けることができる
  15. 15. damage()
  16. 16. Interface // ルールの規定 interface ILife { function damage(int value); } // ルールに基づく実装 class Enemy implements ILife { var hp = 10; public function damage(int value) { hp -= value; } }
  17. 17. Playerはシンプルに class Player { // ILife インターフェイスを持つ相手ならだれでも public void attack(ILife target) { target.damage( 10 ); // damage()を与えちゃうよ } }
  18. 18. 敵がいくら増えても class Boss implements ILife { int hp = 100; public void damage(int value) { hp -= value/2; } } class Magician implements ILife { int hp = 5; public void damage(int value) { hp -= value; } } class BadBoy implements ILife { int hp = 99; public void damage(int value) { hp -= value; } }
  19. 19. Playerは影響を受けない class Player { // ILife インターフェイスを持つ相手ならだれでも public void attack(ILife target) { target.damage( 10 ); } }
  20. 20. クラス図 インターフェイスを 知っていれば
 具体的な相手は知ら なくて良い
  21. 21. 良くなったこと • 意識することが減る • 敵を作ったら damage っていう関数を 必ず作って、Playerにその敵専用の攻 撃メソッドを追加するの忘れないでね • ILifeのインターフェイス実装しといて
  22. 22. 良くなったこと • コンパイル時間の低下 • 敵のロジック修正するたびにPlayerが 再コンパイルされる • 変更した敵のファイルだけ再コンパイル される
  23. 23. インターフェース • チーム開発、大規模開発において重要な 考え方 • 技術仕様のコード化 • テストが書きやすくなる
  24. 24. OCP • 拡張をしても、他のモジュールへ影響を与 えない • 新しい敵を追加しても Player は影響を 受けない • Player のロジックを変更しても敵は影響 を受けない
  25. 25. ちょっと寄り道 class GameManager { Player player; Enemy enemy; // implements ILife Boss boss; // implements ILife public void start() // ゲーム開始時に一度だけ呼ばれる { player = new Player(); enemy = new Enemy(); boss = new Boss(); } public void update() // 毎フレーム呼ばれる { if (KeyDown( A_BUTTON )) // Aボタンが押されていたら player.attack( enemy ); if (KeyDown( B_BUTTON )) // Bボタンが押されていたら player.attack( boss ); } }
  26. 26. こいつ何者? • 役割の明確でないクラス名 • インスタンスの生成・ゲームロジック・ 入力処理。なんでも屋。 • ゲームに出てくるクラスを全部知っている つまり、すべてのクラスに依存している • 世界を知るもの
  27. 27. 依存注入とは Dependency Injection
  28. 28. 新仕様 プレイヤーは武器を装備できて
 敵を攻撃できるんだよ
  29. 29. Code class Weapon { public int power() { return 10; } // 攻撃力 } class Player { public void attack( ILife enemy ) { Weapon weapon = new Weapon(); enemy.damage(weapon.power); } }
  30. 30. 新仕様 新しくて、かっこ良くて、強い武器が
 思いついてしまうんだ…!
  31. 31. Interface interface IWeapon { int power() // 攻撃力 } class SuperSword implements IWeapon { public int power() { return 9999; } // 攻撃力 } class BigGreatAxe implements IWeapon { public int power() { return 100; } // 攻撃力 } class HyperUltimateKnife
 …
  32. 32. Player class Player { IWeapon weapon; public void equip( int type ) { switch(weaponType) { case 1: weapon = new SuperSword(); break; case 2: weapon = new BigGreatAxe(); break; case 3: weapon = new HyperUltimateKnife(); break; } } public void attack( ILife enemy ) { enemy.damage( weapon.power() ); } }
  33. 33. クラス図 Playerがすべての武器に依存してるぞ…
  34. 34. 依存を絶つ Player に誰かが武器を
 渡してあげる (Inject)
  35. 35. 依存注入のパターン class Player { IWeapon equipedWeapon; Player( IWeapon weapon ) { equipedWeapon = weapon; } public void setWeapon( IWeapon weapon ) { equipedWeapon = weapon; } public function attack( ILife enemy ) { enemy.damage( equipedWeapon.power() ); } /* こんな書き方も */ public void setWeaponAndAttack( ILife enemy, IWeapon weapon ) { enemy.damage( weapon.power ); } }
  36. 36. Constructor Injection Player( IWeapon weapon ) { equipedWeapon = weapon; }
  37. 37. Setter Injection public void setWeapon( IWeapon weapon ) { equipedWeapon = weapon; }
  38. 38. Interface Injection public void setWeaponAndAttack( ILife enemy, IWeapon weapon ) { enemy.damage( weapon.power ); }
  39. 39. クラス図 Player は インターフェイスのみに依存
  40. 40. また寄り道 class GameManager { Player player; Enemy enemy; Boss boss; Weapon weapon; public void start() // ゲーム開始時に一度だけ呼ばれる { weapon = new Weapon(); player = new Player( weapon ); // 依存の注入 Constructor Injection enemy = new Enemy(); boss = new Boss(); } public void update() { if (KeyDown( A_BUTTON )) // Aボタンが押されていたら player.attack( enemy ); if (KeyDown( B_BUTTON )) // Bボタンが押されていたら player.attack( boss ); } }
  41. 41. 何が起きているか • Player はインターフェイスさえ知っていれば、 どんな武器でも使いこなせるし、どんな敵にも 攻撃できるようになった • 敵をじゃぶじゃぶ追加できるようになった • 武器をじゃぶじゃぶ追加できるようになった • GameManagerという のクラスがすべての 武器とすべての敵に依存している
  42. 42. 次回DIコンテナ についてやります

×