バックグラウンド
PPPの 100 ページで、Robert Martin は次のように述べています。
「変更のためクローズ」
モジュールの動作を拡張しても、モジュールのソース コードまたはバイナリ コードは変更されません。リンク可能なライブラリ、DLL、または Java .jar のいずれであっても、モジュールのバイナリ実行可能バージョンは変更されません。
また、103 ページでは、非 OCP 設計により既存のクラスが再コンパイルされる、C で記述された例について説明しています。
したがって、すべての witch/case ステートメントまたは if/else チェーンのソース コードを変更するだけでなく、Shape データ構造を使用するすべてのモジュールのバイナリ ファイルを (再コンパイルによって) 変更する必要があります。バイナリ ファイルを変更すると、DLL、共有ライブラリ、またはその他の種類のバイナリ コンポーネントを再デプロイする必要があります。
この本は 2003 年に出版され、例の多くは長いコンパイル時間で悪名高い言語である C++ を使用していることを覚えておくとよいでしょう (ヘッダー ファイルの依存関係が適切に処理されない限り - Remedy の開発者はあるプレゼンテーションでAlan Wakeの完全なビルドには約 2 分しかかかりません)。
したがって、小規模 (つまり、1 つのプロジェクト内) でのバイナリ互換性について議論する場合、OCP (および DIP) の利点の 1 つは、コンパイル時間が短縮されることです。これは、最新の言語やマシンではあまり問題になりません。しかし、大規模な場合、ライブラリが他の多くのプロジェクトで使用されている場合、特にそれらのコードが私たちの管理下にない場合、ソフトウェアの新しいバージョンをリリースする必要がないという利点が引き続き適用されます.
例
バイナリ互換性で OCP に従うオープン ソース ライブラリの例として、JUnit を見てください。JUnit の@RunWithアノテーションとRunnerインターフェースに依存する数十のテスト フレームワークがあるため、JUnit、Maven、IDE などを変更することなく、JUnit テスト ランナーで実行できます。
また、JUnit に最近追加された@Rule アノテーションにより、テスト ライターは、以前はカスタム テスト ランナーが必要だった標準 JUnit テストのカスタム動作にプラグインできます。もう一度、ライブラリ レベルの OCP の例を示します。
対照的に、TestNG は OCP には従いませんが、TestNG と JUnit のテストを異なる方法で実行するための JUnit 固有のチェックが含まれています。TestRunner.run ()メソッドから代表的な行を見つけることができます。
if(test.isJUnit()) {
privateRunJUnit(test);
}
else {
privateRun(test);
}
その結果、TestNG テスト ランナーがいくつかの面でより多くの機能 (たとえば、テストの並列実行をサポートするなど) を持っていても、TestNG を変更せずに他のテスト フレームワークをサポートするように拡張できないため、他のテスト フレームワークはそれを使用しません。(TestNG には-testrunfactory引数を使用してカスタム テスト ランナーをプラグインする方法がありますが、私の知る限りでは、スイートごとに 1 つのタイプのランナーしか許可されません。そのため、JUnit とは異なり、1 つのプロジェクトで多くの異なるテスト フレームワークを使用することはできません。)
結論
ただし、ほとんどの場合、OCP はアプリケーションまたはライブラリ内で使用されます。この場合、基本モジュールとその拡張機能の両方が同じバイナリ内にパッケージ化されます。そのような状況では、OCP はソース コードの保守性を向上させるために使用されますが、再デプロイや新しいリリースを避けるためではありません。変更されていないファイルを再コンパイルする必要がないという潜在的な利点はまだありますが、ほとんどの最新の言語ではコンパイル時間が非常に短いため、それはあまり重要ではありません。
常に心に留めておくべきことは、OCP に従うと、システムがより複雑になるため、費用がかかるということです。Robert Martin は、PPP の 105 ページと章の結論でこれについて語っています。OCP は、最も可能性の高い変更に対してのみ、慎重に適用する必要があります。OCP に従うために先制的にフックを配置するべきではありませんが、フックを必要とする変更が発生した後にのみフックを配置する必要があります。したがって、既存のクラスを変更せずにすべての新機能が追加されたプロジェクトを見つけることはほとんどありません-誰かがそれを学術的な演習として行わない限り(私の直感では、それは非常に難しく、結果として得られるコードはきれいではないと言います).