依存関係逆転の原則（Dependency Inversion Principle） - 逆転ってなんやねん？

# いやいや、いきなり逆転って言われてもなんのこっちゃわからんわ

と思ったので。自分なりに調べたところを記録しておきます。

アーキテクチャについて調べているとよくお目にかかる、オブジェクト指向プログラミングの設計原則[SOLID（Wikipedia）](https://ja.wikipedia.org/wiki/SOLID)の五番目の子（D)だそうです。

# 逆転ってなんやねん？（翻訳：逆転とはどういう意味ですか？）

>ものすごく簡単に結論からいうと、設計上望ましい依存の方向性と、素直に実装しようとしたときの方向性は矛盾しちゃうので、そこをテクニックでカバーして逆転させると、じつはスッキリと望ましい設計通りに実装できますよ！という人類の知恵です。[^1]

[^1]: [よくわかるSOLID原則5: D（依存性逆転の原則）] (https://note.com/erukiti/n/n913e571e8207)より

素直に実装したときの依存の方向と逆。

>処理の流れは、ソースコードの依存性とは逆向きになることに注意しよう。ソースコードの依存性と処理の流れは逆向きになる。だからこそ「依存関係逆転の原則（DIP）」と名付けたのである。[^2]

[^2]: Clean Architecture 達人に学ぶソフトウェアの構造と設計（Robert C. Martin 著／角 征典、高木正弘 訳／アスキードワンゴ）第11章 DIP

ソースコードの依存性と処理の流れが逆。

逆転の雰囲気については、なんとなくわかったような・・・？

# どうやんねん？（翻訳：どのように実現すればよいのですか？具体的に教えてください。）

>>上位のモジュールは下位のモジュールに依存してはならない。どちらのモジュールも、抽象に依存すべきである。
抽象は、実装の詳細に依存すべきではない。実装の詳細が、抽象に依存すべきである。
実践ドメイン駆動設計 p.118
[^3]

[^3]: [1分でわかる依存関係逆転の原則(DIP)](https://qiita.com/wanko5296/items/29e74cc7dd7562624d08)

実装の詳細が、抽象に依存すべき。

例として、MVPパターンでPresenterとViewを考えます。
素直に実装すると、Presenterが以下のようにViewに依存しています。どうやらこれが依存関係逆転の原則に違反しているようです。

```swift:Presenter
class Presenter {
    let view: View
    
    required init(view: View) {
        self.view = view
    }
    
    func updateText(_ text: String) {
        view.setText(text)
    }
}
```
```swift:View
class View: UIView {
    let label: UILabel
    ...
    func setText(_ text: String) {
        label.text = text
    }
}
```

これを抽象を使って、依存性を逆転させます。
つまり、Presenter側で定義した抽象にViewという具象を依存させます。

```swift:Presenter
// ViewProtocolという抽象を定義
protocol ViewProtocol: UIView {
    func setText(_ text: String)
}

class Presenter {
    // Presenterも同じく抽象に依存
    let view: ViewProtocol
    
    required init(view: ViewProtocol) {
        self.view = view
    }
    
    func updateText(_ text: String) {
        view.setText(text)
    }
}
```
```swift:View
// Viewを抽象に依存させる ← 逆転！
class View: UIView, ViewProtocol {
    let label: UILabel
    ...
    func setText(_ text: String) {
        label.text = text
    }
}
```

具体的なコードで見てみると、「ソースコードの依存性と処理の流れが逆」という意味がわかりますね。
Presenterは、実行時には具体的に実装されたViewのインスタンスを通じてメソッドを呼び出す（処理の流れ）けれど、ソースコード上では逆向きに依存してるよね、というお話です。

# なにが嬉しいん？（翻訳：こうすることでどんな利益が得られるのですか？）

>ソフトウェアは「ソフト」になるように考案された……振る舞いを簡単に変更する手段になることを目的としたもの……簡単に変更したくないときは、それを「ハード」ウェアと呼んだ。[^4]

[^4]: Clean Architecture 達人に学ぶソフトウェアの構造と設計（Robert C. Martin 著／角 征典、高木正弘 訳／アスキードワンゴ）第2章 2つの価値のお話

**ソフト**ウェアは振る舞いを簡単に変更できなければいけない。

>依存関係というものがあります。プログラミングの世界では、たとえば、AというモジュールがBというモジュールを読み込む場合、AはBに依存しているといいます。

>このとき、Bを変更するとAにも影響が生じます。このときの当然のことながらBだけの問題ではなく、Aについても影響範囲の調査や改修が必要になります。[^1]

依存関係があると、変更のコストが大きくなる。

>安定依存の原則 （SDP: Stable Dependencies Principle）

>設計原則の一つに「安定依存の原則」があります。「依存の方向は、より安定した方向に向かわなければならない」というものです。実装を進めているとモジュール間の依存は必ず発生します。その方向を安定したモジュールに向かうようにすることで、ソフトウェア全体の修正頻度・修正範囲が低く小さく抑えられるというものです。安定依存の原則に従えば、ソフトウェアの安定性を高めることができます。[^5]

[^5]: [「依存性逆転の原則」の自分なりの解釈](http://at-grandpa.hatenablog.jp/entry/dip)

依存する方向を安定したモジュールに向けるほど、変更に関わるコストが小さくなる。

>抽象インターフェイスの変更は、それに対応する具象実装の変更につながる。一方、具象実装を変更してもインターフェイスの変更が必要になることはあまりない。つまり、インターフェイスは実装よりも変化しにくいということだ。
優れたソフトウェア設計者やアーキテクトは、インターフェイスの変動性をできるだけ抑えようとする。新しい機能を実装するときにも、できる限りインターフェイスの変更なしで済ませられるようにする。これは、ソフトウェア設計の基本中の基本だ。
安定したソフトウェアアーキテクチャは、変化しやすい具象への依存を避け、安定した抽象インターフェイスに依存すべきである。[^2]

具象実装に比べて安定した抽象を依存先とすることで、安定したソフトウェアアーキテクチャに近く。

まとめると、簡単に変更できるようなソフトウェアを作るためには、依存先をできるだけ安定した（変更の少ない）対象にするほうが良いよ。
依存関係逆転の原則は、抽象を依存先にするという方法で、それに貢献しますよ、ということですね。

# ほな、さいなら（翻訳：おわりに）

自分なりには上記のように理解したつもりですが、ほかの本や記事を読んでいるといろんな文脈で使われていて、もう少し違う解釈もあるのかなと思ったりします。
ご意見・ご感想お待ちしております！