プログラミングの記事を読んでいると、「DI」はなんとなく分かっても「コンテナって何?」で一度止まりませんか。
こんにちは、『ゴイノワ』のナギです。わたしも最初は、何かを入れておく箱くらいの意味なのかな、と名前のところで引っかかりました。
先に答えると、DIコンテナは必要な部品を用意して、必要な場所へ渡してくれる仕組みです。ここを起点にすると理解しやすくなります。
DIコンテナとは何?
DIコンテナは、ソフトウェアの部品どうしの依存関係を管理し、必要なオブジェクトを生成して渡す仕組みです。DIは「Dependency Injection」の略です。
日本語では「依存性注入」や「依存性の注入」と呼ばれます。ただ、この訳だけを見ると余計に難しく感じるかもしれませんね。
- DI
-
必要な部品を外から渡す仕組み
- DIコンテナ
-
その部品の生成や受け渡しを担う仕組み
わたしなら、まず「DI」と「DIコンテナ」を同じものとして覚えないようにします。DIは考え方や手法で、コンテナはそれを助ける仕組み、と分けると腑に落ちます。
そもそも依存とは?
ここで一度止まったのが、「依存」という言葉でした。日常では少し重い響きがありますが、プログラムではもっと単純な関係を指します。
たとえば、注文を受け付けるプログラムがメール送信機能を使うなら、注文側はメール送信側を必要としています。この「必要としている関係」が依存です。
一つのクラスの中で必要な部品を直接作ることもできます。ただ、その部品を別のものへ替えたいとき、利用する側のコードまで書き換える場面が出てきます。
DIでは何が変わる?
DIでは、使う側が必要な部品を自分で作るのではなく、外から受け取ります。よく使われるのが、コンストラクタを通して受け取る方法です。
たとえるなら、料理人が畑へ野菜を取りに行くのではなく、必要な食材を厨房まで届けてもらう感じ。料理人は料理そのものに集中できます。
ナギ「誰が部品を用意するの?」が次の疑問です
そこで登場するのがDIコンテナです。どの部品を使うかあらかじめ登録しておき、必要になったときに生成して渡す役割を担います。
DIコンテナがすること
DIコンテナの役割は製品によって差がありますが、基本を追うなら登録・生成・受け渡しの流れを見ると分かりやすいです。
| 項目 | 内容 |
|---|---|
| 登録 | どの部品を使うかコンテナへ知らせる |
| 生成 | 必要になったオブジェクトを作る |
| 受け渡し | 必要としているクラスへ渡す |
| 寿命の管理 | オブジェクトを使い続ける範囲を扱う |
SpringではIoCコンテナがオブジェクトの生成や設定、組み合わせを担います。.NETにも標準のサービスコンテナがあり、登録したサービスを必要な場所へ渡せます。
名前や具体的な使い方は環境ごとに違います。DIコンテナという名前の製品が一つあるわけではありません。ここは取り違えたくないところです。
使うと何がうれしい?
分かりやすい利点は、使う側と使われる側の結びつきを弱くしやすいことです。別の実装へ替えるときも、利用側へ手を入れずに済む場合があります。
テストでも利点があります。本番用の部品ではなく、テスト用に用意した部品へ差し替えやすくなるためです。
ただし、DIコンテナを入れれば自動的に良い設計になるわけではありません。登録する部品が増えるほど、どこで何を登録したか追う必要も出てきます。
IoCコンテナとの違い
DIコンテナを調べると、「IoCコンテナ」という言葉もよく出てきます。ここで似た名前が増えるので、少しややこしく感じるところなんですよね。
IoCは「Inversion of Control」の略で、日本語では「制御の反転」と訳されます。DIは、そのIoCを実現する方法の一つとして扱われます。
そのため、DIを扱う仕組みをIoCコンテナと呼ぶ資料もあります。Springの公式資料では「IoC Container」という呼び方が使われています。
Service Locatorとは別物
もう一つ、DIと並んで出てくるのがService Locatorです。どちらも部品どうしの強い結びつきを避けるために使われますが、受け取り方が違います。
DIでは外側から必要な部品を渡してもらいます。一方のService Locatorでは、使う側がロケーターへ「この部品をください」と探しに行く形です。
似た目的があるので、言葉だけ追うと混ざりやすいところ。わたしは「渡されるのがDI、取りに行くのがLocator」と先に覚えるほうがつかみやすいと思います。
コードではどう登場する?
実際の開発では、「サービスをコンテナへ登録する」「コンストラクタで受け取る」といった形でDIコンテナに触れることがあります。
たとえば.NETでは、インターフェースと実装の組み合わせをサービスとして登録できます。必要なクラス側では、そのインターフェースをコンストラクタで受け取ります。
JavaのSpringでも、コンテナがBeanと呼ばれるオブジェクトを生成し、依存するオブジェクトを渡します。書き方は違っても、根っこの発想はかなり近いです。
まずは「部品を渡す箱」で考える
DIコンテナとは、プログラムが必要とする部品を登録し、生成し、必要な場所へ渡してくれる仕組みです。DIという手法を実際の開発で扱いやすくしてくれます。
Springや.NETなどで呼び方や機能には違いがありますが、「使う側が自分で部品を作らなくてもよい」というところを押さえると、説明を読み進めやすくなります。
次にコードでDIという文字を見かけたら、「この部品は誰が作って、どこから渡されるんだろう?」と一度見てみてください。そこから追うと、DIコンテナの役割がかなり見つけやすくなりますよ。












