Upgrade to Pro — share decks privately, control downloads, hide ads and more …

🤝🏻 依存関係と依存オブジェクト注入

🤝🏻 依存関係と依存オブジェクト注入

社内LTにて、依存関係と依存オブジェクト注入を布教しようと試みましたʕ◔ϖ◔ʔ

関連テーマ(ドメイン駆動設計と依存性逆転の原則):
https://speakerdeck.com/hiroki_hasegawa/domeinqu-dong-she-ji-toyi-cun-xing-ni-zhuan-falseyuan-ze

長谷川広樹

June 25, 2021
Tweet

More Decks by 長谷川広樹

Other Decks in Programming

Transcript

  1. 目次 ▪ なぜ,我々は依存関係を理解する必要がある? ▪ 依存(Dependency) ▪ 依存とは別視点のオブジェクト間関係性 ▪ 合成(Composition) ▪

    集約(Aggregation) ▪ 依存オブジェクト注入(Dependency Injection) ▪ 依存オブジェクト注入の種類 ▪ 依存オブジェクト注入コンテナ(DIコンテナ) ▪ 余談:ドメイン駆動設計のアーキテクチャがわかるぞ! ▪ 『依存性逆転の原則』についてはまた今度
  2. 依存(Dependency) ▪ 依存とは クラスAがクラスBを引数/返却値として使用 ⇓ 『 A 』は『B 』に依存 ▪

    クラス図における依存 (例)UserクラスはUserNameクラスを使用 <?php namespace App\Domain\User\Entity; use App\Domain\User\ValueObject\UserName; final class User { // UserNameに依存 public function method(UserName $name): string { return "Hello! " . $name->getName(); } }
  3. 合成(Composition) ▪ 合成 クラスBはAありきで生成される ▪ クラス図における合成 (例)UserNameはUserありきで生成 <?php namespace App\Domain\User\Entity;

    use App\Domain\User\ValueObject\UserName; final class User { private UserName $name; // データとして保持 public function method(): string { $name = new UserName(); // 合成の関係 return "Hello! " . $name->getName(); } }
  4. 集約(Aggregation) ▪ 集約 クラスBはAと無関係に生成される関係 ▪ クラス図における集約 (例)UserNameはUserとは無関係に生成 <?php namespace App\Domain\User\Entity;

    use App\Domain\User\ValueObject\UserName; final class User { private UserName $name; // データとして保持 public function __construct(UserName $name) { $this->name = $name; } } <?php $name = new UserName(); $user = new User($name); // 集約の関係
  5. 依存(Dependency) ▪ 依存とは クラスAがクラスBを引数/返却値として使用 ⇓ 『 A 』は『B 』に依存 ▪

    クラス図における依存 (例)UserクラスはUserNameクラスを使用 <?php namespace App\Domain\User\Entity; use App\Domain\User\ValueObject\UserName; final class User { // UserNameに依存 public function method(UserName $name): string { return "Hello! " . $name->getName(); } }
  6. 依存オブジェクト注入の種類(1) ▪ コンストラクタインジェクション(優勝!!!) constructメソッド経由で依存対象を渡す. ▪ メリット constructメソッドはインスタンス生成時のみ有効. ⇓ セッターを完全に無くした場合に インスタンス生成後に状態を変更不可能.

    ⇓ 不変的な(Immutable)オブジェクト ⇓ より安全なシステム <?php namespace App\Domain\User\Entity; use App\Domain\User\ValueObject\UserName; final class User { private UserName $name; public function __construct(UserName $name) { $this->name = $name; } } <?php $name = new UserName(); $user = new User($name); // インジェクション
  7. 依存オブジェクト注入の種類(2) ▪ セッターインジェクション セッターメソッド経由で依存対象を渡す. ▪ デメリット インスタンス生成後にオブジェクトの状態を変更可能 ⇓ 可変的な(Mutable)オブジェクト ⇓

    ビジネス上ありえない状態のオブジェクトを作れる. ⇓ セキュリティに穴のあるシステム <?php namespace App\Domain\User\Entity; use App\Domain\User\ValueObject\UserName; final class User { private UserName $name; public function setUserName(UserName $name) { $this->name = $name; } } <?php $user = new User(); $name = new UserName(); $user->setUserName($name); // インジェクション
  8. 依存オブジェクト注入の種類(3) ▪ メソッドインジェクション constructメソッドまたはセッター以外で依存対象 を渡す. ▪ デメリット セッターインジェクションと同じ. ▪ ただし

    セッターと同じように使うわけではなければ,用途 によっては問題はない. (コンストラクタインジェクションしか勝たん!) <?php namespace App\Domain\User\Entity; use App\Domain\User\ValueObject\UserName; final class User { public function method(UserName $name) { $name = $name->getName(); // 何らかの処理 } } <?php $user = new User(); $name = new UserName(); $user->method($name); // インジェクション
  9. 依存オブジェクト注入コンテナ(DIコンテナ) ▪ DIコンテナとは ・依存オブジェクト注入に特化したデザインパターン. ・多くの言語で必須パターンになっている. ▪ PHP ・Pimpleライブラリ ・LaravelのServiceContainer機能 ▪

    Go(ただしGoでは,DIコンテナが黒魔術扱い) ・Google製のWireライブラリ ・Uber製のDigライブラリ <?php use Pimple\Container; use App\Domain\User\Entity\User; use App\Domain\User\ValueObject\UserName; class Container { public function __construct() { $container["user_name"] = function ($container) { return new UserName("Hiroki"); }; // Userへの注入 $container["user"] = function ($container) { return new User($container["user_name"]); }; } }