制御の反転

フレームワークがアプリケーションコードを呼び出す設計原則で、依存性注入の基盤となる概念

設計原則設計パターン

制御の反転とは

制御の反転 (Inversion of Control, IoC) は、プログラムの制御フローをアプリケーションコードではなくフレームワークやコンテナが管理する設計原則である。「ハリウッドの原則 (Don't call us, we'll call you)」とも呼ばれる。

通常のライブラリ利用では、アプリケーションがライブラリを呼び出す。IoC では逆に、フレームワークがアプリケーションのコードを呼び出す。この「制御の方向の反転」が名前の由来だ。

// 通常: アプリケーション → ライブラリ (アプリが制御)
const server = new HttpServer();
server.listen(3000);
const request = server.waitForRequest();  // アプリが制御フローを管理
handleRequest(request);

// IoC: フレームワーク → アプリケーション (フレームワークが制御)
app.get('/users', (req, res) => {
  // Express がリクエストを受け取り、適切なハンドラを呼び出す
  // アプリは「何をするか」だけを定義し、「いつ呼ばれるか」はフレームワークに委ねる
});

IoC の実現手段

IoC は広い概念であり、複数の手段で実現できる。依存性注入 (DI) はその 1 つにすぎない。

手段 仕組み
依存性注入 (DI) 依存オブジェクトを外部から注入 コンストラクタインジェクション
イベントリスナー イベント発生時にフレームワークがリスナーを呼び出す DOM イベント、EventEmitter
テンプレートメソッド 基底クラスがアルゴリズムの骨格を定義し、サブクラスが詳細を実装 React のライフサイクルメソッド
コールバック 処理完了時にフレームワークがコールバックを呼び出す Node.js の非同期 API
設定ファイル フレームワークが設定を読み取り、適切なコンポーネントを組み立てる Spring の XML 設定

Lambda ハンドラーは IoC の典型例

AWS Lambda のハンドラー関数は IoC そのものだ。開発者は「何をするか」(ハンドラーの実装) だけを定義し、「いつ呼ばれるか」(API Gateway のリクエスト、SQS のメッセージ、EventBridge のイベント) は Lambda ランタイムが制御する。

DI による IoC の実践

依存性注入は IoC の中で最も実務的に重要な手段だ。テスト容易性とモジュールの疎結合を実現する。

IoC コンテナ

Java の Spring や .NET の ASP.NET Core には IoC コンテナ (DI コンテナ) が組み込まれている。コンテナが依存関係のグラフを解析し、必要なオブジェクトを自動的に生成・注入する。

TypeScript/Node.js では、tsyringe や InversifyJS が IoC コンテナを提供するが、Lambda のような短命なプロセスでは、手動の DI (コンストラクタインジェクション) で十分なケースが多い。コンテナの導入コストに見合うかを判断する。

よくある誤解

「IoC = DI」

DI は IoC の一手段であり、IoC そのものではない。Express のルーティング、React のコンポーネントライフサイクル、Lambda のイベントハンドラーもすべて IoC だ。

「IoC を使えば自動的にテストしやすくなる」

IoC (特に DI) はテスト容易性の前提条件だが、十分条件ではない。依存を注入可能にしても、インターフェースが巨大すぎたり、副作用が多すぎたりすれば、テストは依然として困難だ。

さらに掘り下げるなら関連書籍が参考になる。

関連用語