あるクラス内で別クラスをインスタンス変数で設定していた場合、コンストラクタでインスタンス化すると依存性が上がってしまいます。なので、DI(依存性の注入)をすることで依存度を下げることが可能です。
DIとは?
あるクラス(アプリケーションサービスクラスなど)をnewする際に引数として関連するクラスをコンストラクタにnewして渡します。
interfaceを作っておいてそれを引数でもらうようにします。newするクラスはinterfaceを継承して作ります。
例
userApplicationServiceというアプリケーションサービスクラスに対して、userレポジトリのインスタンスを注入しています。
1 2 |
const userRepository = new UserRepository(); const userApplicationService = new UserApplicationService(userRepository); |
メリット
- 外部から依存するクラスを渡しているのでクラス間の依存度が下がる。(インターフェースを使っていることが前提だが。):例えば、インポートする対象が下位モジュールがExcelからCSVに挿し変わったところで、高位モジュールの書き換えは一切発生しない。
デメリット
- あちこちでインスタンス 化をさせる記述が生まれる。(依存を下位のコンポーネントに渡しているだけのため)
DIコンテナ
注入される側のクラスと注入する側のクラスの対応リストを保持しておきます。
事前に依存するオブジェクトを登録しておいて使う時になったらDIコンテナ経由でオブジェクトを取得します。この設定などはスタートアップスクリプトなどに登録しておくようにします。
DIコンテナの注意点
DIコンテナを使ったからといって依存関係が逆転するわけではない。あくまでクラスが依存しているオブジェクトを外部から注入できる点が良い。
DIライブラリ(DIフレームワーク)
- Spring Framework(Java)
- google/guice(Java)
- AngularJS(JavaScript:DIフレームワークを内包している)
- InversifyJS(TypeScript)
- TSyringe(TypeScript)
ライブラリなしでDIコンテナを実装する場合の問題点
- decoratorを使用する必要がある。
- reflectionによるメタデータの取得が必要になる。
- TypeScript(を使ってる場合は)のインターフェース情報がコンパイル時に削除されてしまい、DIコンテナの対応づけができない。
この記事へのコメントはありません。