2022年11月に行われた、Dependency Injectionに関する社内共有会の資料です。 DIという言葉の整理と実用例を紹介しています。
Copyright © 2022 RevComm Inc.Introduction to Dependency Injection「DI」 の整理とそのメリット
View Slide
Copyright © 2022 RevComm Inc.⚠今回、限られた時間で紹介するため細部には触れない。以下のマークで補足説明や参考資料を紹介する。Caution 注意✍補足説明🔍参考資料
Copyright © 2022 RevComm Inc.# DI を取り巻く用語の整理と解説・DI はなぜ分かりにくいか・デザインパターンとは・Dependency とは・Dependency Injection とは・Dependency Inversion とは・Injection と Inversion を同時に行う# サンプルコードを用いて DI のメリットを解説# 使い所と気をつけることTOC 目次
Copyright © 2022 RevComm Inc.デザインパターン実装依存性の注入 (Dependency Inejction) と依存性の逆転 (Depedency Inversion) が概念としてある。また、依存性の注入に関しても「具体的な実装 (ライブラリ)」「デザインパターン」が混在している。さらにライブラリでは Dependency Inejction Container を広義の DI として捉えられているものもある。・デザインパターンと実装を切り離して理解する・言葉が表すものを理解するといったことに気をつけることが大事。DI はなぜ分かりにくいか依存性の注入Injection依存性の逆転Inversion「DI はなぜ有用か」「Python で DI する」「DI (SOLID 原則) 理解した」「DI の実装方法」
Copyright © 2022 RevComm Inc.デザイン (設計) を抽象化し、よく見るもの (パターン) に名前を付けたもの。具体的なコードを指しているわけではないので注意。ソフトウェアの文脈で「デザインパターン」と言うと GoF のデザインパターンを指すことが多い。これは、オブジェクト指向言語でのソフトウェア開発のデザインパターン。デザインパターンとは🔍GoF デザインパターンと DI (fukabori.fm)https://fukabori.fm/episode/48🔍O’Reilly ソフトウェアアーキテクチャの基礎https://www.oreilly.co.jp/books/9784873119823/
Copyright © 2022 RevComm Inc.Dependency (依存):概念的には、あるオブジェクト B の中でオブジェクト A の機能を利用すること。Class B の中で Class A のインスタンスを作成している時に、「Class B は Class A に依存している」と言う。開発者がClassB を開発する時には、ClassA を使うことを知らなければならない。Dependency とはClass AClass BClass B depends on Class A.
Copyright © 2022 RevComm Inc.Dependency Injection (依存性の注入):ある ClassB で利用したい ClassA のインスタンスを、第三者から渡すこと。ClassB は与えられたものを利用すれば良いので、ClassB の中では ClassA のインスタンス化をする必要がない。コンストラクタを利用するのが一般的。Dependency Injection とはClass AClass BClass B depends on Class A.第三者Class BPass a Class A instance viaconstructor.✍setter や method を利用する方法もある。Setter は public になってしまうし、method では private だが可変になってしまうので constructor でやるのが良い。Setter vs. Constructor Injection
Copyright © 2022 RevComm Inc.Dependency Inversion Principle (依存性逆転の法則) :SOLID 原則の 1 つ。クラス B をクラス A の実装ではなくインターフェース (IF) に依存させる。こうすることで、依存関係を逆転することができる。Dependency Inversion とはClass AClass BClass B depends Class A.Class B🔍「依存性逆転の原則」と「依存性の注入」を完全に理解したClass AInterface AClass BClass A1Interface AClass A2✍矢印の向きが変わっていないように見えるかもしれません。それぞれをmodule と捉えると、module B の中で module A の interface にのみ依存すればよくなります。これは実質的に module 同士の依存関係が逆転したと言えます。依存性逆転の原則(Dependency Inversion Principle), the D in SOLID
Copyright © 2022 RevComm Inc.Dependency Inversion Principle (依存性逆転の法則) :共通の機能を持つにも関わらず、複数のクラスに別れてしまうケースで有効。1 -> N の依存関係を逆転することで、ロジックがシンプルになる。Dependency Inversion とは
Copyright © 2022 RevComm Inc.Injection をする際に Inversion も行うことで・開発者が Class 内のドメインロジックに集中することができる・疎結合になるので、変更に強くなるといった効果が得られる。「Injection するが Inversion しない」という実装は可能なので注意が必要。Injection と Inversion を同時に行う第三者Class BClass A1Interface AClass A2Class B
Copyright © 2022 RevComm Inc.・Dependency Injection / Inversion はそれぞれデザインパターンである。・Injection することで、依存関係を把握する必要がなくなる。・Inversion することで、1:N の依存関係を 1:1 にすることができる。・Injection と Inversion を合わせることで依存関係をシンプルにしつつ、意識する必要がなくなる。ここまでのまとめ
Copyright © 2022 RevComm Inc.DI のメリットuse_case を injection することで、関数内の処理でどのuse_case を利用するか意識する必要がなくなる。use_case の IF が揃っている前提はあるが、似たような処理をコピペできるので生産性があがる。Injection することで依存関係を把握する必要がなくなる。✍左のコードの例だと、開発者が use_case は execute() によって処理が実行されるという共通認識を持つ必要がある。
Copyright © 2022 RevComm Inc.DI のメリット左の例はログのインターフェースを用意し、RDS 用の実装をしている。開発者がどのDBを利用するか意識する必要がない。インフラの移行に際しても責務が切り離される。Injection と Inversion を合わせることで依存関係をシンプルにしつつ、意識する必要がなくなる。
Copyright © 2022 RevComm Inc.DI のメリットAPI の利用ロジックを Injection することで、storybook や testなどで、同じ type を持つオブジェクトを自由に挿入できる。jest などモックでも可能だが、再利用性や複雑なケースも対応できることを考えると Injection に軍配があがる。Injection と Inversion を合わせることで依存関係をシンプルにしつつ、意識する必要がなくなる。
Copyright © 2022 RevComm Inc.DI の使い所と気をつけること使い所・mock では対応できないようなテスト・レイヤードアーキテクチャのレイヤー間の結合を疎にする。気をつけること・レイヤー間以外の、結合度が高くあるべきコードを DI しすぎない・依存性の逆転がされていない場合は、依存関係が見えづらくなるケースがある🔍DI コンテナの本当の使いどころhttps://www.ulsystems.co.jp/archives/025.html