SOLID原則:開放閉鎖の原則

  • 調べていると、 開放閉鎖 と書いている人と 解放閉鎖 と書いている人がいたが、 開放閉鎖 と書いている人の方が多そうな印象だったので、ここでは 開放閉鎖 にしておく
  • オープン・クローズドの原則 とも言ったりするのかな?

開放閉鎖の原則とは?

  • Open Closed Principle = OCP
  • 拡張できて修正不要の原則

    • そもそも

      既存のクラスやシステムが機能拡張可能である状態 = Open:開いている

      機能拡張の際に修正を要しない状態 = Close:閉じている というらしい

  • Open Closed = 拡張できて修正不要の原則(そのまま読める

機能拡張の方法には2つ存在する

  1. 既存のコードを修正する
  2. コードを新しく追加する ← 今回の原則では、こちらで機能拡張するという前提。

開放閉鎖の原則では、機能拡張する際に、 既存のコードを修正することなく、コードを追加することができるプログラムにしましょうという原則


最近、よく思うのですが、使われているソフトウェアは、基本的に常に仕様変更や機能拡張が入ると思っていた方が良さそう

逆に、1回作って、何も変更や機能拡張がないソフトウェアは、必要ではないソフトウェアで、使われていないソフトウェアとも言えるのかなと思います

新卒の頃から、仕様変更で自分が書いたコードが無駄になってしまう現象に虚しさと悲しみとで、😑 ってなった時も何度かありましたが、どこの業界の開発部隊でも開発している限り、そういうものなんだなと思い始めました

よくない例

class Payment:
    
    def pay(self, type: str) -> int:
        # type別の決済をする
        if type == 'credit':
            # クレジットカードで決済する
            return XXXXXXX

        if type == 'applePay':
            # ApplePayで決済する
            return XXXXXXX
        

payment = Payment()

# ApplePayで支払う
payment.pay(type='applyPay')

PayPayも対応できるようにしてほしい との要望があった

  • 修正案は・・・
if type == 'PayPay':
    # PayPayで決済する
    return XXXXXXX

Payment クラスに追加してしまうと・・・・

開放閉鎖の原則は守られていないコードだ

と言えてしまいますね

既存のコードである Payment クラスに変更を加えてしまっているので 🙅‍♀️ ですね

開放閉鎖の原則を守るコードに書き換えてみる

Class Payment:

    def pay(self) -> int:
        # 決済する
        pass

# クレジットカードのクラスを作成
Class Credit(Payment):
    """クレジットカードのクラス."""

# ApplePayのクラス
Class ApplePay(Payment):
    """ApplePayのクラス."""
    

# PayPayのクラス
Class PayPay(Parment):
    """PayPayのクラス."""

paypay = PayPay():
price = paypay.pay()

決済の大元となるクラスを作成し、それぞれの決済がPaymentクラスを継承するように修正

このようにすると、既存のコードは書き換えることなく、PayPayクラスを追加するだけで機能拡張することができ、開放閉鎖の原則は守られているコードになった

参考:https://kanoe.dev/blog/open-closed-principle/

開放閉鎖の原則のメリットは?

既存のコードに手を加えていないので、バグるリスクが小さくなる(少なくとも既に動いているコードはバグらなさそう)

オブジェクト指向に限らず守りたい最重要原則 "open/closed principle - OCP - 開放/閉鎖原則"(SOLID原則より) - Qiita


この前書いた、単一責任の原則とメリットは似てますね 🤔

メリットが薄っぺらくなってしまいましたが、概要については理解できたので終わり

こちらも徐々に学んでいきたいところですねぇ・・・