2.6 OPC (Open-Closed Principle)
別名、開閉原則ともいわれており、有名な設計原則のSOLIDのOがこれである。
変更や拡張に対して開いていて(変更がしやすく)、かつ
変更に対して閉じている(他の部分が影響を受けにくい)
変更時のコストを抑えられる。
何を心掛ければいいのか?
そもそもこの開閉原則は、SOLIDのSである単一責任原則を満たしていないと、
破られてしまうことが多い。
そのため、まずは単一責務、データとそのデータを必要とする処理をまとめた
カプセル化を行うことをスタートとしたうえで、必要に応じてインターフェイスなどを
用いて変動から保護するという方法をとることが望ましい。
GRASPのポリモーフィズムや変動からの保護のパターンがまさにそれである。
以下の記事を参照。
注意事項 -Design By Contract-
ただし、その際にインターフェイスを用いた場合には、
契約による設計を意識したインターフェイス設計を行わないといけない。
何も考えずに、事前事後条件などを設定したインターフェイス設計では、
正しく、ポリモーフィズムは成立しない。
事前条件として必要な、引数の型は、正しく指定されているのか?
事後条件としての戻り値の型は、どの具体でも適用可能な型として抽象化されているのか? 投げる例外の種類はどうなっているのか?
などを考慮し、どのオーバーライドした実装要素と置き換えても、ポリモーフィズムが成立するように、リスコフの置換原則を満たしているかのチェックを随時しないといけない。
そのためには、インターフェイスの事前事後不変条件をすべて満たしていることをチェックする必要があるし、そのようなインターフェイスをボトムアップ式に設計しないといけない。
DRY原則をあえて破りOCPを満たしたい場合
他のものとの関係性
アプリケーションアーキテクチャの領域だけでなく、他の領域においてもこの設計原則が、適用されるケースがあるので、いくつか紹介したいと思う。
サービス設計×OCP
まずはアプリケーションアーキテクチャ領域における、もっとマクロなサービスレベルのお話し。
あるサービスBに依存した、他のサービスAが下図のようにあるとする。
この時、当たり前な話だが、サービスに入った変更は、なるべくならサービスAにまで影響しないでほしい。
そのために、非同期的な通信設計にするなど様々な方法があるが、
結局は【修正時の変更を対象のコンテキスト境界内に封じ込めることでコストを抑える】
という思考に集約される。
データアーキテクチャ×OCP
データアーキテクチャにおいても、この開閉原則は重要である。
あるサブジェクトの変更が、他のサブジェクトに影響しないように設計することが求められる。