A Day In The Life

とあるプログラマの備忘録

依存関係逆転の原則

依存関係逆転の原則とは

  • 上位のモジュールは下位のモジュールに依存してはならない。どちらのモジュールも「抽象」に依存すべきである
  • 「抽象」は実装の詳細に依存してはならない。実装の詳細が「抽象」に依存すべきである
という原則です。
まずはこのクラス図を見てください。
パッケージがお互いに依存している図
この図ではパッケージAとパッケージBが互いに依存していて二つのパッケージを分離することが出来ません。
1つ目の図のようにパッケージが互いに依存しているときはインターフェースを使うことによって依存関係を一方通行にすることが出来ます。

具体的にはDaoインターフェースをパッケージAに作ってやり、パッケージBでDaoインターフェースを実装してやればよいのです。

依存関係が単方向になった図

2つ目の図ではパッケージBからAへの依存関係残るもののパッケージAからBへの依存関係はなくなっています。

これでパッケージAだけを切り離すことが出来るようになりましたね。

インターフェースを使うことによりAパッケージとBパッケージの依存関係が逆転しました。これが「依存関係逆転の法則」の由来になっています。
では実際にどのように実装すればよいのでしょうか?

はじめに思いつくのは下記のようなコードだと思います。

public class HogeBusiness {
 public void invoke() {
  Dao dao = new DaoImple();
  dao.findAll();
  …
  ……
 }
}

これではせっかくインターフェースを作ってもnewのところでパッケージBのクラスを参照してしまうのであまり意味がありません。
そこでSpringやSeasar2などのDIコンテナを使って依存性を注入するようにしてやればパッケージBのクラスを参照しなくてすみます。

コードは

public class HogeBusiness {
 private Dao dao = null;
 public void setDao(Dao dao) {
  this.dao = dao;
 }
 public void invoke() {
  dao.findAll();
  …
  ……
 }
}

となりあとはXML定義ファイルに依存関係を書いてやればOKです。

XML定義ファイルの書き方は各DIコンテナによって違うのでここでは割愛します。

DIコンテナについて興味のある方はSpringとかSeasar2で調べてみてください。
インターフェースを使って依存性をなくすことでクラスの再利用性が高まり、それがそのままパッケージの再利用性にもつながります。

DIのメリットもこの原則とセットで考えるとよく理解できるんじゃないかと思います。

それにしてもこの原則コロンブスの卵のような発想ですよね。考えた人は凄い。