2025-03-29
オブジェクトが依存するインスタンスを自分で生成するのではなく、外部から注入することで、オブジェクト間の依存関係を解消する設計パターンのことです。 DIを使うことで、オブジェクト間の結合度を下げ、テストしやすいコードを書くことができます。
具体的な例をみて、DIのメリットを確認します。
依存下院系を外部で設定できるようにすることで、Car
クラスはEngine
の生成を自分でしないため、他のEngine実装(例:ElectricEngine)を簡単に差し替えることができます。
また、テストに時にはMockEngine
クラスを注入することで、テストしやすいコードに変更することもできます。
https://inversify.io/ InversifyJSとは、TypeScript向けのDIコンテナです。 InversifyJSを使うことで、依存関係を自動で解決することができます。 まずは使い方をみていきましょう。
@injectable
デコレータを使うことで、Katana
とNinja
クラスをDI可能なクラスに変更します。
@inject
デコレータを使うことで、Ninjya
クラスがKatana
クラスを依存していることを示します。
container.bind
メソッドを使うことで、クラスと実装のバインドを行います。
container.get
メソッドを使うことで、DIコンテナからインスタンスを取得します。
イメージ的には、外部依存のクラスをcontainer.bind
メソッドで外部依存を登録して、container.get
メソッドで外部依存が設定されたインスタンスを取得するという感じです。
ここからは、InversifyJSの機能について詳しくみていきます。 この機能をみていくことで、DIについて理解を深めることができます。
Bindingは、クラスと外部依存のクラスをバインドする機能です。
Bindingをすることで、コンテナに追加され、container.get
メソッドでインスタンスを取得することができます。
tsconfig.json
でemitDecoratorMetadata
オプションを有効にすることで、@inject
デコレータを使わずにバインドすることもできます。
emitDecoratorMetadata
とは?
emitDecoratorMetadata
は、クラスの型情報(メタデータ)をコンパイル時に生成して出力するためのオプションです。オプションを有効にすることで、デコレータのメタデータを出力することができます。
https://qiita.com/SoraKumo/items/1e05c68e9add1d62690a reflect-metadata
とは?
メタデータを操作するためのライブラリです。個のライブラリは実行時に自分自身の構造を調べたり操作したりする機能を実現するために私用されます
https://qiita.com/shibukawa/items/35a84ceb12923782d03e bindingのScope scopeはインスタンスを生成するときのキャッシュ戦略を指定することができます。
Request
classの中で同じオブジェクトを使う場合は同じインスタンスを使うSingleton
container.get
をしたときにすでにキャッシュ済みのインスタンスがある場合はキャッシュ済みのインスタンスを使うTransient
常に新しいインスタンスを生成するそれぞれのコンテナには親コンテナを持たせることができます。 親コンテナを持たせることで、アプリの関心を分割しすることができ、より柔軟なDI設計を行うことができます。 依存が注入されたときに、InversifyJSは現在のコンテナから親コンテナに向かって依存を探しに行きます。
DI Hierarchyを使うことで、複雑な依存関係を管理し、コードをクリーンに保つことができます。
Activation
Activationは、インスタンスが生成されるときにるときにonActivation
メソッドを使ってインスタンスに対して処理を行うことができます。
Deactivation
Deactivationは、インスタンスが破棄されるときにonDeactivation
メソッドを使ってインスタンスに対して処理を行うことができます。
Snapshotは、コンテナの状態を保存する機能です。 Snapshotを使うことで、コンテナの状態を保存して、後で復元することができます。 この機能はデバッグやテスト、コンテナの変更を監視したいときに便利です。