Angular_依存性の注入(DI)とは #261日目
依存性の注入 (DI: dependency injection) はAngular2+のコアコンセプトです。インジェクターと呼ばれる抽象概念を用いて、「依存性コンシューマー」と「依存性プロバイダー」間のやり取りを簡単にします。
言葉の意味は後ほど触れますが、DIとはつまり方法論のことです。Angularに限らず、保守性の高いコードを書くことを目的としたソフトウェア設計原則とパターンのセットとして、あらゆるところで導入されている概念です。
一言でいうと、DIは疎結合を作ることを目的としています。
DIが生まれた経緯
起源はJavaのコミュニティで、Martin Fowler氏が2004-2005年頃に定義した言葉とのことです。Inversion of Control (IoC)という概念が当時存在しており、その概念を具体化する言葉としてDIが設定されました。
そのIoC (制御の逆転)とは、「呼び出す側」と「呼び出される側」が従来のプログラムと逆になる現象を指します。ジョークとして「ハリウッドの原理」と呼ばれることもあるそうです(我々を呼ぶな。我々が呼ぶ。)。必要になったらこちらから呼びます、という感じの意味ですね。
これはフレームワークを使ったアプリケーション開発全般に当てはまる特性でもあって、開発者が定義したメソッドがアプリケーションコードから直接呼ばれることはほぼなく、呼ばれるタイミングはフレームワーク側に委ねられています。
IoCとDIの関係
IoCは「制御の逆転」、DIは「依存関係に対する制御の逆転」と表現できます。IoCの方が広義の概念で、DIはIoCに内包されているようなイメージです。
DIとは具体的にどういうことか
例えばあるクラスAの中に、メイン機能Xとサブ機能Yがあり、それぞれクラスAの中で定義していたとします。サブ機能はクラスAの中で直接定義しているかもしれませんし、外部サービスや別クラスをインポートして使っているかもしれません。
この時、クラスAはサブ機能Yに依存していることになります。そしてサブ機能Yを変更したい場合など、クラスAの保守が複雑になってしまいます。
DIが意味する「依存関係の制御の逆転」とは、このサブ機能Yを外出しして、クラスAの中で必要なタイミングで呼び出すようにすることで、依存度の低減を図ることです。
Angularでは、これを以下の方法で実現します
依存性プロバイダー(サブ機能Y):
「XXXX.service.ts」ファイルに@Injectableデコレーターを付けたクラスです。
ここで定義した内容をインジェクションして、コンポーネントで使用できるようになります。
@Injectable()
class HeroService {}
依存性コンシューマー(クラスA):
「XXXX.component.ts」ファイルに定義された各コンポーネントです。
@Componentデコレーターの「providers」フィールドに依存性プロバイダーを登録できます。
@Component({
selector: 'hero-list',
template: '...',
providers: [HeroService]
})
class HeroListComponent {}
コンポーネント側では、普通にクラス内のconstructorで変数として宣言することも可能です。
constructor(private heroService: HeroService) { }
ここまでお読みいただきありがとうございました!!