以前書いたコードが読みづらくて困った時、以前のプロジェクトのソースコードを適用し辛くて困った時に読むと役に立つ話。

# コードの再利用性についての話

コードがぐちゃぐちゃになった。スパゲティコードで自分の書いたコードが読めない。
以前のプロジェクトからソースコードを持ってきたい。
似たようなコードがあるから簡単に使いまわしたいのに、使いまわすための作業がしんどい。

ある、ありますよね。僕も散々悩みました。

ヒントを貰いました。でも分かりませんでした。それで勉強しました。探しました。そして見つけました。

そう、あるんです。世の中には。それを考え出した方達がいらっしゃるんです。

その対策には色々と方法があって、その中の一つに「依存性逆転の原則」と言うものがあります。

その「依存性逆転の原則」と、そもそも「依存」とはなにかについても分からなかったので「依存ってなんだよ！」などと叫びたい同志に向けて紹介を。


## 環境

使用している言語は Unity / C# です。

かなり昔のバージョンでも使えると思います。

## 用語

### その1

|キーワード|意味|
----|----
|フローチャート|視覚的にプログラムを表現する、流れ図|
|クラス図|クラスやインターフェイスなどの関係を表現する|
|依存|詳細に左右されていると言う事, 実際にコレとかアレを使ってる状態のことです|
|実現|インターフェイスをクラスに実装する事、インターフェイスのメソッドを実際のコードを書いて継承関係も記すこと|
|詳細|具体的な仕様、実際に使っているもの、こと|
|モジュール|クラスやインターフェイスなどの集まり|

</dd>
</dl>

## 依存性逆転の原則にまつわる色々

### 依存とは何か？
まず、「依存性逆転の原則」における、「依存」ってなに？と言う話です。

ソースコードにおいて、あるクラス（ここでは `Bullet`）内で、特定のクラス（ここでは `Enemy`）を使用することを依存すると言います。

```C#:Attackers:Bullet.cs
public class Bullet : MonoBehaviour {
    void OnTriggerEnter(Collider collision) {
        if(collision.CompareTag("Enemy")) {
            var enemyItem = collision.GetComponent<Enemy>();
            if(enemyItem != null) {
                enemyItem.Damage(1);
            }
        }
    }
}
```
```C#:Effectables:Enemy.cs
public class Enemy : MonoBehaviour {
    public void Damage(int value){
        Debug.Log("Enemy is Damaged" + value + " point.")
    }
}
```

例えばこんなコードがあったとして、ダメージを受ける敵以外に破壊できる壁 `Wall` クラスを追加するとします。

対象はタグで識別しています。

```C#:Effectables:Wall.cs
public class Wall : MonoBehaviour {
    public void Damage(int value){
        Debug.Log("Object is broken")
    }
}
```

```C#:Attackers:Bullet.cs 状態2
public class Bullet : MonoBehaviour {
    void OnTriggerEnter(Collider collision) {
        if(collision.CompareTag("Enemy")) {
            var enemyItem = collision.GetComponent<Enemy>();
            if(enemyItem != null) {
                enemyItem.Damage(1);
            }
        }
        if(collision.CompareTag("Wall")) {
            var wallItem = collision.GetComponent<Wall>();
            if(wallItem != null) {
                wallItem.Damage(1);           
            }
        }
    }
}
```

この時、`Bullet` クラスが `Enemy` クラスに依存しているため、新しい `Wall` クラスを作成した時に `Bullet` に変更を加えなければならなくなります。
```plantuml
namespace Attackers{
    class Bullet {
    }
}

namespace Effectables{

    class Enemy {
        void Damage(int value)
    }
    
    class Wall {
        void Damage(int value)
    }
    
    Attackers.Bullet ..> Enemy
    Attackers.Bullet ..> Wall
}
```


つまり、衝突判定が行われたターゲット(この時の `Effectables` の二つのクラス)の種類の変更や追加、修正に `Bullet` クラスのソースコードが左右されてしまうと言う事です。

ですので、日本語の「依存」そのままの意味で使われています。

「依存」と言う言葉をプログラムで聞き慣れていない方は直感的に理解するのは難しいかも知れませんが、落ち着いて関係を見直せば、「確かに依存している」ことは理解できると思います。

:::note info
想像してみて下さい。Enemy がたとえ個人的な理由（気が向いたとか）でふらふらと Damage メソッドのシグネチャ（引数の数、種類、メソッドの名前、返り値のこと）を変更したとしても、その度に Bullet は慌てて自分のコードを直さなればいけません。

この状態だと Enemy の気分に Bullet は振り回されることになります。

どうでしょう、依存していると言っていること、通じたでしょうか。
:::

 `Effectables` モジュールに所属している`Enemy` 、 `Wall` クラスのメソッドの仕様を両方把握しなければそれぞれのクラスを利用することは出来ません。

この時、把握するクラスが増えるほど管理は大変になります。

### 依存の向きと相互依存
それでは依存性逆転（の原則）とはなんでしょうか。
</br>
依存する場合、向きとして、前出の `Bullet` クラスが `Enemy` クラスに依存しています。先ほどの変更でも分かるように、`Bullet` クラスのシグネチャを変更しても `Enemy` クラスは変更する必要がないのでこの時の依存の向きは一方向です。

また、`Bullet` と `Enemy` がどちらのシグネチャを修正した時でもお互いに変更が必要だと、相互依存していることになり、管理が大変に（再利用性に乏しく）なります。
</br>

:::note
相互依存についてはまた別の機会に。
:::

### 実際の例
`Bullet` は扱う Collision の種類が多ければ多いほど中身を把握することに労力を必要としました。

しかし、`Enemy` と `Wall` のダメージを受ける処理ってよく見ると中身は違うけど、良く似てると思いませんか？

`Bullet` クラスから見ると両方に同じ事をしていると思いませんか？

これを、`Enemy`, `Wall` に共通するインターフェイスに切り出して（抽象化させて）から `IDamageable` を実現させると、以下のようになります。

```C#:Attackers
public class Bullet : MonoBehaviour {
    void OnTriggerEnter(Collider collision){
        IDamageable item = collision.GetComponent<IDamageable>();
        if(item != null) {
            item.Damage(1);
        }
    }
}

public interface IDamageable {
    void Damage(int value);
}
```

```C#:Effectables
public class Enemy : MonoBehaviour, IDamageable {
    public void Damage(int value){
        Debug.Log("Enemy is Damaged" + value + " point.")
    }
}

public class Wall : MonoBehaviour, IDamageable {
    public void Damage(int value){
        Debug.Log("Object is broken")
    }
}

```
```plantuml
namespace Attackers{
    class Bullet {
    }

interface IDamageable {
    void Damage(int value)
    }
    Bullet ..> IDamageable
}
namespace Effectables{

    class Enemy {
        void Damage(int value)
    }
    
    class Wall {
        void Damage(int value)
    }
    
    Attackers.IDamageable <|.. Enemy
    Attackers.IDamageable <|.. Wall
}
```

お分かりでしょうか。
`Enemy` と `Wall` は `IDamageable` インターフェイスを実現しています。
この時、`Bullet` は `IDamageable` インターフェイスを把握するだけで指示を出すことが出来るのです。

`Bullet` クラスは同じことしているだけなのに、`Enemy` と `Wall` の両方の事を知ってなくちゃいけなかったのが、`IDamagearable` を `Enemy` も `Wall` も使えるよ！と`Ballet` さんに伝えると `Bullet` さんは `IDamagerable` と言うやり方だけ気にすれば同じように処理が出来、管理が楽になります。

### インターフェイスのモジュールへのまとめ方の話
`Bullet` クラスが変われば指示できる行動や指示できる内容が変わる可能性があるため、この時、`Bullet` と `IDamageable` インターフェイスは同じモジュールとして扱う事になります。
また、`Effectables` はインターフェイスが変更されれば、仕様が左右されてしまうため、この `IDamagerable` インターフェイスに `Effectables` は依存しています。

### 依存性が逆転する話
つまり、`Attackers` モジュールの `Bullet` が `Effectables` の `Enemy` に依存していたのが、今度は  `Effectables` モジュール(の二つ)が `Attackers` モジュール(の `IDamagerable`)に依存していて、最初の例と依存する向きが逆転している事が図からも分かります。これが依存性逆転の原則です。

クリーンアーキテクチャから引用させて頂きます。

>ソースコードの依存関係が（具象ではなく）抽象だけを参照しているもの。それが最も柔軟なシステムである。(クリーンアーキテクチャより引用)


しかし、この時注意するべきなのは

>String クラス は具象であり、これを抽象にするのは無理がある。<中略>String クラスはほかのクラスに比べて非常に安定している。<中略>プログラマは String の内容がコロコロ変わることなど心配しなくていい。<中略>依存したくないのは、システム内の変化しやすい具象要素だ。開発中のモジュールや、頻繁に変更され続けているモジュールがその対象になる。(クリーンアーキテクチャより引用)

とあるように、再利用性を高めたいのは、プログラマが記述するシステムにおいて、変更が頻繁に行われる、今回の例で言う、`IDamagerable` インターフェイスを実現できるクラスと、それを利用するクラスのような具体的なソースコードがある時の事です。

`String` クラスのように安定しているモジュールはインターフェイスで切り分ける事を気にしなくて良いのよ、ってことです。

### 流動的なモジュールに対するプロジェクト間の共有について
`Effectables` モジュールは、自立的に動く `Enemy` クラスとしてダメージを受けたり、点滅して無敵時間を得たり、壁のようにダメージを受けたら壊れるだけで動かない Wall と頻繁に追加、変更します。
また、`Enemy` は横スクロールアクションとしてジャンプしたり横に往復したりしますが、プロジェクトが変われば、見下ろし型で縦横に移動するように変化したりもします。

依存性逆転の原則を使わなければ、その度に Bullet は OnTriggerEnter2D の Collision の対象を増やしたり修正する事になります。

僕はその時に何も知らなかったので、SometimeBullet, AnytimeBullet, OOBullet とどんどんとクラスが増えて行って両方のプロジェクトを両立させることがとても大変でした。

:::note
まとめ
その使われる側(下位、 `Effectables` モジュール)を抽象の使う側(上位、`Attakers` モジュールの `IDamageable` インターフェイス)に依存させる事で修正、管理（再利用性）を容易にしようとするものを依存性逆転の原則と言います。
:::
クリーンアーキテクチャはとても難しい本だと思います。一息で理解しようとしても中々出来ないと思います。

人生は長いです。楽しむことも難しいですが、回り道、寄り道をして気長にプログラマライフを送ると言うのも一つの手だと思います。

これからもしまた何か機会があれば、また何か記事を書いてみたいと思います。

「依存性逆転の原則」は設計原則の一つである SOLID 原則の内の一つです。


### 参考文献など

OnTriggerEnter の使い方は以下の記事を参考にできます。
- [XR-HU3/【Unity】OnTriggerを利用した当たり判定を理解しよう！](https://xr-hub.com/archives/7499)


参考文献：
- [クリーンアーキテクチャ](https://www.amazon.co.jp/Clean-Architecture-%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%81%AE%E6%A7%8B%E9%80%A0%E3%81%A8%E8%A8%AD%E8%A8%88-%E3%82%A2%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%89%E3%83%AF%E3%83%B3%E3%82%B4-%EF%BC%B2%EF%BD%8F%EF%BD%82%EF%BD%85%EF%BD%92%EF%BD%94-%EF%BC%A3%EF%BC%8E%EF%BC%AD%EF%BD%81%EF%BD%92%EF%BD%94%EF%BD%89%EF%BD%8E-ebook/dp/B07FSBHS2V/ref=sr_1_1?keywords=clean+architecture&qid=1690058245&sprefix=Clean%2Caps%2C195&sr=8-1)


参考記事：
設計の話で参考にした記事
- [toRisouPさん/Unity開発で使える設計の話＋Zenjectの紹介](https://www.slideshare.net/torisoup/unityzenject) 

「CleanCode」「リーダブルコード」なども大変勉強になるかと思います。