🧑‍🎤

SOLIDについて書き記していくだけ#2

2024/05/04に公開

Open Closed Principal : オープン・クローズドの原則

ソフトウェアの構成要素は拡張に対してオープンで、修正に対して閉じていなければならない

→ソフトウェアを拡張する際には既存のコードに対して修正を行わずにできるようにしておく

目的

機能追加を容易にすることができる
既存のコードに修正を加えないで良い為、機能追加によるデグレのリスクを減らすことができる

コード例

違反例🙅‍♀️
以下のコードでは”dog”と”cat”の鳴き声しか用意されていない
更に動物の種類を増やすためにはmatch文の修正が必要になってくる
また、種類を増やしていくとAnimalSoundクラスが肥大化する

class AnimalSound
{
    public function __construct(
	    private readonly string $name
    ){
    }

    // 鳴き声を返す
    public function bark() : void
    {
      // 新しく動物を追加(拡張)したい場合は条件を修正する必要がある
         $barkSound = match($this->name) {
            "dog" => "bowwow",
            "cat" => "meow",
            default => "No Sound"
        };
        
        echo $barkSound;
    }

}

改善例🙆‍♀️
以下のようにAnimalクラスを用意する
AnimalSoundクラスのプロパティにはAnimalオブジェクトを持たせる
新しく動物を扱いたい場合には、扱いたい動物のAnimalオブジェクトを用意して
AnimalSoundクラスのインスタンス化を行えば良いだけ
→動物の追加に対してのAnimalSoundクラスの修正は不要になった!

// 名前と鳴き声を持たせたAnimalクラス
class Animal
{
    public function __construct(
        private readonly string $name,
        private readonly string $barkSound
    ){   
    }

    public function getName(): string
    {
        return $this->name;
    }

    public function getBarkSound(): string
    {
        return $this->barkSound;
    }
}

// Animalオブジェクトをプロパティにもつ動物の音に関するクラス
class AnimalSound
{
    public function __construct(
        private readonly Animal $animal
    ) {
    }

    // 鳴く
    public function bark() : void
    {
        echo $this->animal->getBarkSound();
    }
}

※interface等を使えばより良い設計ができる気がするけど、、、(本当はもっと良いコード書けるんだからね!!)

Discussion