8
6

More than 3 years have passed since last update.

開放閉鎖の原則

Last updated at Posted at 2020-04-27

開放閉鎖の原則 (Open/closed principle)

拡張に対して開いて (open) いなければならず、
修正に対して閉じて (closed) いなければならない

上記原則に従ったソフトウェアは、既存のソースコードを変更することなく、振る舞いを変更することができる

wikipedia

ある日の会話

私「なんとなくしかわからない...。つまり、どういうこと?」

夫「SOLID原則の中で、一番何言ってるのかわからない箇所かも」
夫「実際コードを書いて説明するよ」

悪い例_コントローラー
class BadSampleController
{
    public function BadSample()
    {
        $class = new Update(new DbConnection());

        //エンドユーザー
        $class->updateUser($userName, $address);
        //管理者ユーザー
        $class->updateAdmin($userName, $address, $authority);
    }
}
悪い例_下位ロジック
class Update
{
    public function __construct(DbConnection $connection)
    {
        $this->connection = $connection;
    }

    public function updateUser($userName, $address)
    {
        $this->connection->begin();

        // $userName, $addressの更新処理

        $this->connection->commmit();
    }

    public function updateAdmin($userName, $address, $authority)
    {
        $this->connection->begin();

        // $userName, $address, $authorityの更新処理

        $this->connection->commmit();
    }
}

兄「この例だと、更新対象が増える度に、メソッドを追加しなくちゃならないから修正に対して閉じてないということ」

私「わかりやすくいうと、「店舗ユーザー」を追加する場合は、Updateクラスにメソッドを追加することになるってことか・・・」

私「逆に、更新対象が増えてもメソッドを追加しなくてもいいのが修正に対して閉じてるのね」

兄「そ。じゃあどうすればいい?って思うよね?」

私「うん。...インターフェイスとか使うのかな?」

兄「正解! コードを書いてみようか」

良い例_コントローラー
class SampleController
{
        $class = new Update(new DbConnection());

        //エンドユーザー
        $class->update(new User());
        //管理者ユーザー
        $class->update(new Admin());
}
良い例_下位ロジック
class Update
{
    public function __construct(DbConnection $connection)
    {
        $this->connection = $connection;
    }

    public function update(UpdateInterface $update)
    {
        $this->connection->begin();

        $update->updateUser();

        $this->connection->commmit();
    }
}
良い例_インターフェイス
interface UpdateInterface
{
    public function updateUser();
}
良い例_エンドユーザークラス
class User implements UpdateInterface
{
    public function __construct(DbConnection $connection)
    {
        $this->connection = $connection;
    }

    /**
     * エンドユーザーに対する更新処理を記載する
     */
    public function updateUser(){
        // $userName, $addressの更新処理
    }
}
良い例_管理者クラス
class Admin implements UpdateInterface
{
    public function __construct(DbConnection $connection)
    {
        $this->connection = $connection;
    }

    /**
     * 管理者ユーザーに対する更新処理を記載する
     */
    public function updateUser(){
        // $userName, $address, $authorityの更新処理
    }
}

兄「こうすると、下位ロジックにメソッドを追加しなくてもよくなったでしょ」

私「たしかに!」
私「じゃあ、店舗ユーザーを増やしたいってなった時は、店舗ユーザークラスの作成とコントローラーへの追記だけでOKってことだよね?」

兄「そうだよ」

私「めっちゃいいやつ....」

おわり

関連_SOLID原則の記事

単一責任の原則

8
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
6