🐥

依存性の逆転のいちばんわかりやすい説明

2022/02/01に公開

依存性逆転の原則とは

SOLIDの原則のD、依存性逆転の原則(Dependency Inversion Principle)とは、ざっくり言えば、プログラムの重要な部分が、重要でない部分に依存しないよう設計すべきであるということです。
これを実現するためには、依存関係の向きを自由に制御するテクニックが非常に役立ちます。
この記事では、そのテクニックを簡単な具体例を交えて紹介します。

依存性の逆転のやり方

例えばクラスAがクラスBに依存している状況を考えます。

具体例: Aは挨拶するとき、Bに挨拶の仕方を教えてもらって挨拶している

class B { // クラスBの定義
  getHowToGreet() { // 挨拶の仕方を取得する関数
    return "こんにちは"
  }
}

class A { // クラスAの定義
  greet() { // コンソールに挨拶を出力する関数
    const b = new B() // BをAの内部でインスタンス化
    
    const greetMessage = b.getHowToGreet() // Bを用いて挨拶の仕方を取得
    
    console.log(greetMessage) // 取得した挨拶を出力
  }
}

const a = new A()
a.greet()

この依存関係を次のように逆転したいとします。

これを行うには、次のことをします。

  • BのインターフェイスIBを用意する
  • IBを継承してBを実装する
  • AはIBに依存させる

すると以下のようになります。

このIBをAの一部ととらえたとき、BはAの一部であるIBに依存して継承を行っています。つまり、AとBの依存関係は逆転しているといえます。

具体例

A
interface IB { // BのインターフェイスIB
  getHowToGreet(): string
}

class A {
  b: IB // Bのインターフェイスに依存する

  // コンストラクタで外からBの実体を受け取る
  constructor(b: IB) {
      this.b = b
  } 

  greet() {
      // 受け取ったBの実体を用いる
      const greetMessage = this.b.getHowToGreet()
    
      console.log(greetMessage)
  }
}
B
class B implements IB { // IBを継承してBを実装
  getHowToGreet() {
    return "こんにちは"
  }
}
main
const b = new B() // Bは外で生成して渡す
const a = new A(b) 
a.greet()

ちなみに、依存するものをコンストラクタなどで外から入れてもらうことを 依存性の注入(Dependency Injection) といいます。依存性の逆転(Dependency Inversion) も頭文字がDIなのでややこしいです。

このテクニックを用いて、プログラムの一番重要な部分を担うクラスが、データベースやWebフレームワークなどを用いるクラスに依存しないように設計することにより、依存性逆転の原則を達成できます。

より具体的な説明

https://zenn.dev/chida/articles/e46a66cd9d89d1

続き

続きを書いたのでこちらも読んでもらえると嬉しいです。

https://zenn.dev/naas/articles/dependency-inversion-without-class

Discussion