0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DI(依存性注入)って、結局なにが嬉しいの?

0
Posted at

DI(依存性注入)って、結局なにが嬉しいの?

— Springを「雰囲気」で使わないための第一歩 —

はじめに

Springを触っていると、ほぼ確実に出会う言葉があります。

DI(Dependency Injection / 依存性注入)

正直なところ、こんな理解で止まっていませんか。

  • @Autowired を付けると動く
  • new しなくていいから楽
  • よく分からないけど Spring のお作法

今回はこの「よく分からないけど便利なやつ」を、
Springを一旦忘れて、Javaのコードレベルで整理します。


まず「DIがない世界」を見てみる

いきなりDIの話をすると混乱するので、
まずは DIを使っていないコード から。

public class UserService {

    private UserRepository userRepository = new UserRepository();

    public void register(String name) {
        userRepository.save(name);
    }
}

一見、何の問題もなさそうに見えます

  • UserServiceUserRepository を使う
  • 普通に new して呼び出している

では、このコードの 何が困る のでしょうか。


問題①:差し替えができない

例えばテストを書きたくなったとします。

@Test
void registerTest() {
    UserService service = new UserService();
    service.register("test");
}

ここで UserRepository が、

  • DBに接続する
  • 実際にINSERTする

という実装だったらどうでしょう。

テストのたびにDBが必要になります。
これはなかなかつらい。


問題②:UserServiceが「具体クラス」を知りすぎている

UserService は本来、

「ユーザーを登録する」というビジネスロジック

だけを気にしたいはずです。

しかしこのコードでは、

new UserRepository();

という 生成責任 まで背負っています。

  • どのRepositoryを使うか
  • どうやって作るか

この判断を UserService がしているのがポイントです。


依存性注入(DI)の考え方

ここでようやくDIの登場です。

DIの本質は、とてもシンプル。

「使う側が、作るな。渡してもらえ」

コードで見るとこうなります。

public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public void register(String name) {
        userRepository.save(name);
    }
}

UserService はこう言っています。

  • UserRepositoryは必要
  • でも「どう作るか」は知らない
  • 誰かが用意して渡してくれ

これが 依存性注入 です。


DIによって何が変わったのか

1. 差し替え可能になった

UserRepository mockRepo = new MockUserRepository();
UserService service = new UserService(mockRepo);
  • 本番用Repository
  • テスト用Repository

自由に切り替え られます。


2. 責務が分離された

  • UserService
    • ビジネスロジックに集中
  • 外側のコード
    • 依存関係の組み立てを担当

「何をするか」と「どう組み立てるか」が分離されました。


Springは「DIを自動化する仕組み」

ここまで、Springの話は一切していません。

実はこれが重要です。

Springがやっていることは、

  • new の代わりに
  • DIコンテナが
  • 依存関係を組み立てて
  • 注入してくれる

ただそれだけ。

@Service
public class UserService {

    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
}

@Service@Repository は、
DIコンテナへの登録ルール にすぎません。

魔法ではありません。


よくある勘違い

「DI = Spring」

違います。
DIは 設計の考え方、Springは 実装手段 です。

@Autowired を付ければDI」

付けなくても、コンストラクタインジェクションならDIです。
むしろこちらが推奨されます。


まとめ

DIの嬉しさを一言で言うと、

コードを「柔らかく」すること

  • テストしやすい
  • 差し替えやすい
  • 変更に強い

Springはその土台の上に立っています。

DIが腹落ちすると、
「なぜServiceを分けるのか」
「なぜinterfaceを切るのか」
が自然に見えてきます。


次回予告

次はDIとセットで語られがちな、これ。

「なぜService層を分けるのか?」

Controllerに全部書いてはいけない理由を、
設計目線で掘っていきます。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?