実務での導入ポイント
DI は全てのクラスに一律導入するものではありません。受注と商品のように、仕様変更が起きやすい境界から始めるのが実践的です。
どこから導入するか
- 商品情報取得、在庫照会、通知送信などの外部連携
- 環境差分が出る箇所(本番/開発で実装を切替える箇所)
- テストで置き換えたい箇所
interfaceとDIの使い分け
実務では「まず interface を作る」だけで止まりがちですが、それだけでは不十分です。 interface は契約、DI は受け渡しです。両方そろって初めて差し替え可能になります。
- interface を作って差し替え先の型を揃える
- 利用側クラスはコンストラクタで受け取る(DI)
- 実装選択は Spring 設定側に寄せる
コンストラクタ注入を基本にする
public class OrderService {
private final ProductGateway productGateway;
public OrderService(ProductGateway productGateway) {
this.productGateway = productGateway;
}
}
コンストラクタ注入は、 「このクラスが何に依存しているか」が定義で明示されるため、 可読性と安全性が高くなります。
避けたいアンチパターン
- DI コンテナから直接 `getBean()` して依存を取りに行く
- 便利だからと何でも interface 化して抽象化しすぎる
- 小さなユーティリティまで過剰に DI 化して複雑化する
導入チェックリスト
- 受注処理の流れを書き出し、「商品取得」「通知」「課金」など差し替え候補を特定する
- 差し替え候補に interface を導入し、受注処理側は interface に依存させる
- コンテナ設定で実装を束ねる
- 単体テストでモック注入し、恩恵を確認する
Spring Boot では DI が標準機能です。 `@Service`, `@Repository`, `@RestController` を使い、 コンストラクタで依存を受け取る形をまず徹底すると失敗しにくくなります。