オープン・クローズドの原則(OCP)

OCP:The Open-Closed Principle

ソフトウェアの構成要素(クラス、モジュール、関数など)は拡張に対して開いて(OPEN)いて、修正に対して閉じて(CLOSE)いなければならない。

拡張に対して開いているとは?

モジュールの振る舞いを拡張できるということ。
仕様変更に対して、モジュールに新たな振る舞いを追加することでその変更に対処する。

修正に対して閉じているとは?

モジュールの振る舞いを拡張しても、すでにコンパイルされてバイナリ形式となっているDLLやjarファイルを変更する必要はない。

鍵は「抽象」にあり

具体的には、実装に依存しないように抽象クラス(インターフェース)を利用しろということらしい。
つまり、追加要求が発生した場合はその派生クラスを作成することで用意に機能を拡張できる。→OPEN
また、呼び出し側となるクラスは抽象クラス(インターフェース)を呼び出しているだけで実装には依存していない為、機能が拡張されても呼び出し側のコードを変更する必要はない。→CLOSE

「先を見越した構造」と「自然な構造」

それでは、プログラムにどんどん抽象化を適用させた方が良いのかといえば答えはNoだ。
抽象化はむやみに使用するのではなく、もっとも頻繁に変更される部分にだけ的を絞って適用するべきであり、抽象化しないと決定することも抽象化すると決定することと同じくらい重要なことなのだ。
なぜなら不必要な抽象化はソフトウェアの設計を不必要に複雑にする為だ。
今は必要ないが将来必要となるかもしれないという理由で、複雑な構造にしてしまうことは決して好ましいことではない。

結局のところ・・・

抽象化すべきかしないべきかの選択は、設計者の手に委ねられる。
設計者は起こりうるだろう変更を予測し、最小減にOCPを適用しようとするだろう。
勘があたれば勝者で外れれば敗者というわけだ。
しかし、ほとんどの場合、勘は外れ、不必要な複雑さが導入されることになる。

結局のところ、あらゆる状況に対応する完璧な設計など存在しない。
先のことをあれこれ時間をかけて考え、むやみに抽象化して不必要な複雑さを導入するよりも最もシンプルで自然な設計をしておき、実際に抽象が必要となった時点で組み込むべきだ。
変更を覚悟するということだ。
ただ、プロジェクトの終盤での変更は大変だし、できれば早期に変更できた方が良い。

その為に次のようなアプローチを実践する。

  • テストファースト
  • 短いサイクルで開発する
  • 今必要な機能を優先して開発し、頻繁にユーザへ提示する
  • 最も重要な機能から優先的に開発する