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

More Decks by Hiroki Hasegawa (長谷川広樹)

Other Decks in Programming

Transcript

  1. 依存関係

    依存オブジェクト注入
    株式会社ユニクエスト
    長谷川広樹
    github.com/hiroki-it
    @Hiroki__IT

    View Slide

  2. 自己紹介
    ▼ お仕事
    最近:クラウドインフラ、IaC、CICD、...
    以前:DDD
    ▼ 関心のある技術領域
    ・クラウドインフラ
    ・IaC
    ・DDD
    github.com/hiroki-it
    @Hiroki__IT
    長谷川 広樹 (はせがわ ひろき)
    株式会社ユニクエスト

    View Slide

  3. 目次
    ■ なぜ,我々は依存関係を理解する必要がある?
    ■ 依存(Dependency)
    ■ 依存とは別視点のオブジェクト間関係性
    ■ 合成(Composition)
    ■ 集約(Aggregation)
    ■ 依存オブジェクト注入(Dependency Injection)
    ■ 依存オブジェクト注入の種類
    ■ 依存オブジェクト注入コンテナ(DIコンテナ)
    ■ 余談:ドメイン駆動設計のアーキテクチャがわかるぞ!
    ■ 『依存性逆転の原則』についてはまた今度

    View Slide

  4. なぜ,我々は依存関係を理解する必要がある?
    オブジェクト間の依存関係を
    意識しながら
    実装されてますでしょうか??

    View Slide

  5. なぜ,我々は依存関係を理解する必要がある?
    基本的なMVCから始まりアーキテクチャには
    オブジェクト間の依存関係を工夫して
    保守性の高いシステムを開発しようとする思想がある

    依存関係を理解しなければ
    アーキテクチャを正しく使えない!(持論)

    View Slide

  6. 依存(Dependency)
    ■ 依存とは
    クラスAがクラスBを引数/返却値として使用

    『 A 』は『B 』に依存
    ■ クラス図における依存
    (例)UserクラスはUserNameクラスを使用
    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();
    }
    }

    View Slide

  7. 依存から少し離れて補足

    View Slide

  8. 依存とは別視点のオブジェクト間関係性
    ■ 合成と集約
    クラスAがクラスBを『データとして保持』.

    『 A』と『B 』は
    合成(Composition)/集約(Aggregation)の関係を持つ
    ■ 両者の異なる点
    クラスAによって,クラスBのインスタンス生成がどのように制限される
    かで分類

    View Slide

  9. 合成(Composition)
    ■ 合成
    クラスBはAありきで生成される
    ■ クラス図における合成
    (例)UserNameはUserありきで生成
    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();
    }
    }

    View Slide

  10. 集約(Aggregation)
    ■ 集約
    クラスBはAと無関係に生成される関係
    ■ クラス図における集約
    (例)UserNameはUserとは無関係に生成
    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;
    }
    }
    $name = new UserName();
    $user = new User($name); // 集約の関係

    View Slide

  11. 依存の話に戻ります

    View Slide

  12. 依存(Dependency)
    ■ 依存とは
    クラスAがクラスBを引数/返却値として使用

    『 A 』は『B 』に依存
    ■ クラス図における依存
    (例)UserクラスはUserNameクラスを使用
    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();
    }
    }

    View Slide

  13. 依存オブジェクト注入(Dependency Injection)
    ■ 依存オブジェクト注入とは
    クラスAに『引数として』クラスBに渡すこと.
    ■ 依存性注入と訳さないこと
     『依存性を注入する』
    が概念を適切に説明していないという問題

    『依存対象のオブジェクトを注入する』
    = 依存オブジェクト注入
    https://little-hands.hatenablog.com/entry/2018/05/27/dependency-injection

    View Slide

  14. 依存オブジェクト注入の種類(1)
    ■ コンストラクタインジェクション(優勝!!!)
    constructメソッド経由で依存対象を渡す.
    ■ メリット
    constructメソッドはインスタンス生成時のみ有効.

    セッターを完全に無くした場合に
    インスタンス生成後に状態を変更不可能.

    不変的な(Immutable)オブジェクト

    より安全なシステム
    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;
    }
    }
    $name = new UserName();
    $user = new User($name); // インジェクション

    View Slide

  15. 依存オブジェクト注入の種類(2)
    ■ セッターインジェクション
    セッターメソッド経由で依存対象を渡す.
    ■ デメリット
    インスタンス生成後にオブジェクトの状態を変更可能

    可変的な(Mutable)オブジェクト

    ビジネス上ありえない状態のオブジェクトを作れる.

    セキュリティに穴のあるシステム
    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;
    }
    }
    $user = new User();
    $name = new UserName();
    $user->setUserName($name); // インジェクション

    View Slide

  16. 依存オブジェクト注入の種類(3)
    ■ メソッドインジェクション
    constructメソッドまたはセッター以外で依存対象
    を渡す.
    ■ デメリット
    セッターインジェクションと同じ.
    ■ ただし
    セッターと同じように使うわけではなければ,用途
    によっては問題はない.
    (コンストラクタインジェクションしか勝たん!)
    namespace App\Domain\User\Entity;
    use App\Domain\User\ValueObject\UserName;
    final class User
    {
    public function method(UserName $name)
    {
    $name = $name->getName();
    // 何らかの処理
    }
    }
    $user = new User();
    $name = new UserName();
    $user->method($name); // インジェクション

    View Slide

  17. 依存オブジェクト注入の種類(4)
    インターフェースインジェクションは割愛...󰢛

    View Slide

  18. 依存オブジェクト注入コンテナ(DIコンテナ)
    ■ DIコンテナとは
    ・依存オブジェクト注入に特化したデザインパターン.
    ・多くの言語で必須パターンになっている.
    ■ PHP
    ・Pimpleライブラリ
    ・LaravelのServiceContainer機能
    ■ Go(ただしGoでは,DIコンテナが黒魔術扱い)
    ・Google製のWireライブラリ
    ・Uber製のDigライブラリ
    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"]);
    };
    }
    }

    View Slide

  19. 余談:ドメイン駆動設計のアーキテクチャがわかるぞ!(1)
    ■ オニオンアーキテクチャ(@little_hand_s さんの資料がおすすめ)
    ・依存関係が,ビジネスロジックを置くドメイン層に向かうように実装.
    ・ドメイン層は,それ以外のロジック層や外部ライブラリに一切依存しない.
    little hands' lab(https://little-hands.hatenablog.com/entry/2017/10/11/075634)

    View Slide

  20. 余談:ドメイン駆動設計のアーキテクチャがわかるぞ!(2)
    ■ クリーンアーキテクチャ(@nrslib さんの資料がオススメ)
    ・依存関係が,ビジネスロジックを置くエンティティ層に向かうように実装.
    ・エンティティ層は,それ以外の層や外部ライブラリに一切依存しない.
    https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html

    View Slide

  21. 『依存性逆転の原則』についてはまた今度
    『依存性逆転の原則』
    抽象(インターフェース)に依存するように実装する思想
    話が長くなるのでまた今度... 󰢛

    View Slide

  22. 最後に
    テーマと関係ないけど
    Gopherくん超かわいい!!!
    by Takuya Ueda (https://twitter.com/tenntenn)
    The Gopher character is based on the Go mascot designed by Renée French.

    View Slide