Dependency Injectionとは

42
Dependency Injectionとは doi

Transcript of Dependency Injectionとは

Page 1: Dependency Injectionとは

Dependency Injectionとはdoi

Page 2: Dependency Injectionとは

依存とはDependency

Page 3: Dependency Injectionとは

依存とは• 僕はパソコンが無いと生きていけない

• 僕はパソコンに依存

• ネットがないと僕は生きていけない

• 僕はネットとパソコンが無いと成立しない状態

Page 4: Dependency Injectionとは

例えば

Page 5: Dependency Injectionとは

Codeclass 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 ); } }

Page 6: Dependency Injectionとは

Codeclass 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 ); } }

Page 7: Dependency Injectionとは

クラス図Player は Enemy と Boss に依存してる

Page 8: Dependency Injectionとは

依存の影響

Page 9: Dependency Injectionとは

Open-Closed Principle

“オープン・クローズドの原則”

Page 10: Dependency Injectionとは

敵を増やそうマジシャン、狂熊、ワルガキ 凶悪でかっこいいモンスターのアイデアがじゃぶじゃぶ湧き出る…!!

Page 11: Dependency Injectionとは

Codeclass 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 ); } }

Page 12: Dependency Injectionとは

クラス図Player はいろんな敵を知っている状態じゃないと成立しない

Page 13: Dependency Injectionとは

依存を減らしたい

• Playerの他者への依存は膨らむばかり

• 依存をなんとか減らせないか

Page 14: Dependency Injectionとは

共通のインターフェイス• クラスの持つべき性質をルール化する • 基底クラス

• C# の interface, C++なら多重継承

• Duck Typing

• ルールを決める手段は言語や処理系によって様々

• ルール:ダメージを受けることができる

Page 15: Dependency Injectionとは

damage()

Page 16: Dependency Injectionとは

Interface// ルールの規定 interface ILife { function damage(int value); }

// ルールに基づく実装 class Enemy implements ILife { var hp = 10; public function damage(int value) { hp -= value; } }

Page 17: Dependency Injectionとは

Playerはシンプルにclass Player { // ILife インターフェイスを持つ相手ならだれでも public void attack(ILife target) { target.damage( 10 ); // damage()を与えちゃうよ } }

Page 18: Dependency Injectionとは

敵がいくら増えても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; } }

Page 19: Dependency Injectionとは

Playerは影響を受けないclass Player { // ILife インターフェイスを持つ相手ならだれでも public void attack(ILife target) { target.damage( 10 ); } }

Page 20: Dependency Injectionとは

クラス図インターフェイスを知っていれば 具体的な相手は知らなくて良い

Page 21: Dependency Injectionとは

良くなったこと• 意識することが減る

• 敵を作ったら damage っていう関数を必ず作って、Playerにその敵専用の攻撃メソッドを追加するの忘れないでね

• ILifeのインターフェイス実装しといて

Page 22: Dependency Injectionとは

良くなったこと• コンパイル時間の低下

• 敵のロジック修正するたびにPlayerが再コンパイルされる

• 変更した敵のファイルだけ再コンパイルされる

Page 23: Dependency Injectionとは

インターフェース• チーム開発、大規模開発において重要な考え方

• 技術仕様のコード化

• テストが書きやすくなる

Page 24: Dependency Injectionとは

OCP• 拡張をしても、他のモジュールへ影響を与えない

• 新しい敵を追加しても Player は影響を受けない

• Player のロジックを変更しても敵は影響を受けない

Page 25: Dependency Injectionとは

ちょっと寄り道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 ); } }

Page 26: Dependency Injectionとは

こいつ何者?• 役割の明確でないクラス名

• インスタンスの生成・ゲームロジック・入力処理。なんでも屋。

• ゲームに出てくるクラスを全部知っているつまり、すべてのクラスに依存している

• 世界を知るもの

Page 27: Dependency Injectionとは

依存注入とはDependency Injection

Page 28: Dependency Injectionとは

新仕様

プレイヤーは武器を装備できて敵を攻撃できるんだよ

Page 29: Dependency Injectionとは

Codeclass Weapon { public int power() { return 10; } // 攻撃力 }

class Player { public void attack( ILife enemy ) { Weapon weapon = new Weapon(); enemy.damage(weapon.power); } }

Page 30: Dependency Injectionとは

新仕様

新しくて、かっこ良くて、強い武器が思いついてしまうんだ…!

Page 31: Dependency Injectionとは

Interfaceinterface IWeapon { int power() // 攻撃力 }

class SuperSword implements IWeapon { public int power() { return 9999; } // 攻撃力 }

class BigGreatAxe implements IWeapon { public int power() { return 100; } // 攻撃力 }

class HyperUltimateKnife …

Page 32: Dependency Injectionとは

Playerclass 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() ); } }

Page 33: Dependency Injectionとは

クラス図Playerがすべての武器に依存してるぞ…

Page 34: Dependency Injectionとは

依存を絶つ

Player に誰かが武器を渡してあげる (Inject)

Page 35: Dependency Injectionとは

依存注入のパターン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 ); } }

Page 36: Dependency Injectionとは

Constructor Injection Player( IWeapon weapon ) { equipedWeapon = weapon; }

Page 37: Dependency Injectionとは

Setter Injection public void setWeapon( IWeapon weapon ) { equipedWeapon = weapon; }

Page 38: Dependency Injectionとは

Interface Injectionpublic void setWeaponAndAttack( ILife enemy, IWeapon weapon ) { enemy.damage( weapon.power ); }

Page 39: Dependency Injectionとは

クラス図Player は インターフェイスのみに依存

Page 40: Dependency Injectionとは

また寄り道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 ); } }

Page 41: Dependency Injectionとは

何が起きているか• Player はインターフェイスさえ知っていれば、どんな武器でも使いこなせるし、どんな敵にも攻撃できるようになった

• 敵をじゃぶじゃぶ追加できるようになった

• 武器をじゃぶじゃぶ追加できるようになった

• GameManagerという謎のクラスがすべての武器とすべての敵に依存している

Page 42: Dependency Injectionとは

次回DIコンテナについてやります