$30 off During Our Annual Pro Sale. View Details »

Introduction to Dependency Injection 「DI」の整理とそのメリット

RevComm_inc
February 07, 2023

Introduction to Dependency Injection 「DI」の整理とそのメリット

2022年11月に行われた、Dependency Injectionに関する社内共有会の資料です。
DIという言葉の整理と実用例を紹介しています。

RevComm_inc

February 07, 2023
Tweet

More Decks by RevComm_inc

Other Decks in Technology

Transcript

  1. Copyright © 2022 RevComm Inc.
    Introduction to Dependency Injection
    「DI」 の整理とそのメリット

    View Slide

  2. Copyright © 2022 RevComm Inc.
    ⚠今回、限られた時間で紹介するため細部には触れない。
    以下のマークで補足説明や参考資料を紹介する。
    Caution 注意
    ✍補足説明
    🔍参考資料

    View Slide

  3. Copyright © 2022 RevComm Inc.
    # DI を取り巻く用語の整理と解説
    ・DI はなぜ分かりにくいか
    ・デザインパターンとは
    ・Dependency とは
    ・Dependency Injection とは
    ・Dependency Inversion とは
    ・Injection と Inversion を同時に行う
    # サンプルコードを用いて DI のメリットを解説
    # 使い所と気をつけること
    TOC 目次

    View Slide

  4. Copyright © 2022 RevComm Inc.
    デザインパターン
    実装
    依存性の注入 (Dependency Inejction) と依存性の逆転 (Depedency Inversion) が概念としてある。
    また、依存性の注入に関しても「具体的な実装 (ライブラリ)」「デザインパターン」が混在している。
    さらにライブラリでは Dependency Inejction Container を広義の DI として捉えられているものもある。
    ・デザインパターンと実装を切り離して理解する
    ・言葉が表すものを理解する
    といったことに気をつけることが大事。
    DI はなぜ分かりにくいか
    依存性の注

    Injection
    依存性の逆

    Inversion
    「DI はなぜ有用か」
    「Python で DI する」
    「DI (SOLID 原則) 理解した」
    「DI の実装方法」

    View Slide

  5. Copyright © 2022 RevComm Inc.
    デザイン (設計) を抽象化し、よく見るもの (パターン) に名前を付けたもの。
    具体的なコードを指しているわけではないので注意。
    ソフトウェアの文脈で「デザインパターン」と言うと GoF のデザインパターンを指すことが多い。
    これは、オブジェクト指向言語でのソフトウェア開発のデザインパターン。
    デザインパターンとは
    🔍GoF デザインパターンと DI (fukabori.fm)
    https://fukabori.fm/episode/48
    🔍O’Reilly ソフトウェアアーキテクチャの基礎
    https://www.oreilly.co.jp/books/9784873119823/

    View Slide

  6. Copyright © 2022 RevComm Inc.
    Dependency (依存):
    概念的には、あるオブジェクト B の中でオブジェクト A の機能を利用すること。
    Class B の中で Class A のインスタンスを作成している時に、「Class B は Class A に依存している」と言う。
    開発者がClassB を開発する時には、ClassA を使うことを知らなければならない。
    Dependency とは
    Class A
    Class B
    Class B depends on Class A.

    View Slide

  7. Copyright © 2022 RevComm Inc.
    Dependency Injection (依存性の注入):
    ある ClassB で利用したい ClassA のインスタンスを、第三者から渡すこと。
    ClassB は与えられたものを利用すれば良いので、ClassB の中では ClassA のインスタンス化をする必要がない。
    コンストラクタを利用するのが一般的。
    Dependency Injection とは
    Class A
    Class B
    Class B depends on Class A.
    第三者
    Class B
    Pass a Class A instance via
    constructor.
    ✍setter や method を利用する方法もある。
    Setter は public になってしまうし、method では private だが可変になってし
    まうので constructor でやるのが良い。
    Setter vs. Constructor Injection

    View Slide

  8. Copyright © 2022 RevComm Inc.
    Dependency Inversion Principle (依存性逆転の法則) :
    SOLID 原則の 1 つ。クラス B をクラス A の実装ではなくインターフェース (IF) に依存させる。
    こうすることで、依存関係を逆転することができる。
    Dependency Inversion とは
    Class A
    Class B
    Class B depends Class A.
    Class B
    🔍
    「依存性逆転の原則」と「依存性の注入」を完全に理解した
    Class A
    Interface A
    Class B
    Class A1
    Interface A
    Class A2
    ✍矢印の向きが変わっていないように見えるかもしれません。それぞれを
    module と捉えると、module B の中で module A の interface にのみ依存
    すればよくなります。
    これは実質的に module 同士の依存関係が逆転したと言えます。
    依存性逆転の原則(Dependency Inversion Principle), the D in SOLID

    View Slide

  9. Copyright © 2022 RevComm Inc.
    Dependency Inversion Principle (依存性逆転の法則) :
    共通の機能を持つにも関わらず、複数のクラスに別れてしまうケースで有効。
    1 -> N の依存関係を逆転することで、ロジックがシンプルになる。
    Dependency Inversion とは

    View Slide

  10. Copyright © 2022 RevComm Inc.
    Injection をする際に Inversion も行うことで
    ・開発者が Class 内のドメインロジックに集中することができる
    ・疎結合になるので、変更に強くなる
    といった効果が得られる。
    「Injection するが Inversion しない」という実装は可能なので注意が必要。
    Injection と Inversion を同時に行う
    第三者
    Class B
    Class A1
    Interface A
    Class A2
    Class B

    View Slide

  11. Copyright © 2022 RevComm Inc.
    ・Dependency Injection / Inversion はそれぞれデザインパターンである。
    ・Injection することで、依存関係を把握する必要がなくなる。
    ・Inversion することで、1:N の依存関係を 1:1 にすることができる。
    ・Injection と Inversion を合わせることで依存関係をシンプルにしつつ、意識する必要がなくなる。
    ここまでのまとめ

    View Slide

  12. Copyright © 2022 RevComm Inc.
    DI のメリット
    use_case を injection することで、関数内の処理でどの
    use_case を利用するか意識する必要がなくなる。
    use_case の IF が揃っている前提はあるが、似たような処理をコ
    ピペできるので生産性があがる。
    Injection することで依存関係を把握する必要がなくなる。
    ✍左のコードの例だと、開発者が use_case は execute() によって処理が
    実行されるという共通認識を持つ必要がある。

    View Slide

  13. Copyright © 2022 RevComm Inc.
    DI のメリット
    左の例はログのインターフェースを用意し、RDS 用の実装をして
    いる。
    開発者がどのDBを利用するか意識する必要がない。インフラの移
    行に際しても責務が切り離される。
    Injection と Inversion を合わせることで依存関係をシンプルにしつつ、意識する必要がなくなる。

    View Slide

  14. Copyright © 2022 RevComm Inc.
    DI のメリット
    API の利用ロジックを Injection することで、storybook や test
    などで、同じ type を持つオブジェクトを自由に挿入できる。
    jest などモックでも可能だが、再利用性や複雑なケースも対応で
    きることを考えると Injection に軍配があがる。
    Injection と Inversion を合わせることで依存関係をシンプルにしつつ、意識する必要がなくなる。

    View Slide

  15. Copyright © 2022 RevComm Inc.
    DI の使い所と気をつけること
    使い所
    ・mock では対応できないようなテスト
    ・レイヤードアーキテクチャのレイヤー間の結合を疎にする。
    気をつけること
    ・レイヤー間以外の、結合度が高くあるべきコードを DI しすぎない
    ・依存性の逆転がされていない場合は、依存関係が見えづらくなるケースがある
    🔍DI コンテナの本当の使いどころ
    https://www.ulsystems.co.jp/archives/025.html

    View Slide