web-dev-qa-db-ja.com

(/ did)Bertrand Meyerは、サブクラス化が「クローズ」モジュールを拡張する唯一の方法であると考えるのはなぜですか?

マイヤーのオブジェクト指向のソフトウェア構築(1988)で、彼は オープン/クローズド原則 を次のように定義しています。

  • モジュールがまだ拡張可能である場合、モジュールは開いていると見なされます。たとえば、フィールドに含まれるデータ構造にフィールドを追加したり、フィールドが実行する一連の機能に新しい要素を追加したりできるようにする必要があります。
  • モジュールが他のモジュールで使用できる場合、そのモジュールは閉じていると見なされます。これは、モジュールが明確で安定した説明(情報を隠すという意味でのインターフェース)を与えられていることを前提としています。

彼は続けて言う:

モジュールを再び開く場合は、古いバージョンに依存しているため、すべてのクライアントを再度開いて更新する必要があります。 …[この問題]は、モジュールを新しい関数またはデータ要素で拡張する必要があるたびに発生し、直接および間接クライアントの変更をトリガーします。 ...設計とプログラミングへの古典的なアプローチでは、オープンとクローズの両方のモジュールを作成する方法はありません。

このジレンマに対するMeyerの解決策は次のとおりです。既存のクラスを変更してライブラリモジュールを拡張しないでください。代わりに、既存のクラスをサブクラス化する新しいモジュールを作成し、新しいクライアントがその新しいモジュールに依存するようにします。

1988年、私はTurbo PascalとBlankenship Basicでおもちゃ(手続き型)プログラムを書いていたが、21世紀の専門家としての経験は、JVM、CLR、および動的言語であるので、Meyerの意味がわからない。 「設計とプログラミングへの古典的なアプローチ」。

whyクライアントモジュールを再度開く必要があるMeyerの1つの具体的な例(より多くのメンバーを必要とする、より多くのメンバーを必要とする列挙体のswitchステートメント)は、十分に妥当と思われます。ただし、ライブラリモジュールに機能を追加するたびに更新する必要があるとの主張はほとんど正当化されません(== --- == )すべてのクライアント

この主張が1988年に自明のように思われた歴史的な理由はありますか?たとえば、関数やデータ構造をC静的ライブラリに追加すると、下位互換性のあるAPIでもクライアントを再コンパイルする必要があるようにレイアウトが変更されましたか?それともメイヤーは、APIの下位互換性を強制するためのメカニズムについて話しているだけなのでしょうか。

19
David Moles

私の知る限り、この質問はバートランドマイヤー自身が回答しており、答えは「この声明は正確ではない」です。設計とプログラミングへの古典的なアプローチでは、実際にcanは、オープンとクローズの両方のモジュールを作成する方法になります。

これを見つけるには、この本の第2版(9年後に出版された1997年)を研究する必要があります。 第2版のまえがきによれば、

更新ではなく、徹底的なリワークの結果。元のバージョンの段落は変更されていません。 (実際にはほとんど1行ではありません。)

特に、あなたを混乱させる声明は消えました。 「§3.35つの原則」にOpen-Closed主義の章がまだあり、「§14.7継承の概要」にこのトピックの詳細な議論がありますが、初版のステートメントはありませんもう。

代わりに、従来の方法とは異なり、OOアプローチではより便利で慣用的な方法に焦点を当てていますが、

継承のおかげで、O-O開発者は以前の方法で可能だった方法よりもはるかに段階的なソフトウェア開発アプローチを採用できます...(§3.3)

この二重の要件 (open and closed) ジレンマのように見え、古典的なモジュール構造は手掛かりを提供しません。しかし、継承はそれを解決します。クラスは、コンパイルされ、ライブラリに格納され、ベースライン化され、クライアントクラスによって使用される可能性があるため、閉じられています。しかし、新しいクラスはそれを親として使用し、新しい機能を追加し、継承された機能を再宣言するため、それもオープンです。このプロセスでは、オリジナルを変更したり、クライアントを妨害したりする必要はありません...(§14.7)

また、ここでMeyerが「クラシックアプローチ」とは何を意味するのか不思議に思われるため、これらの説明は§4.7従来のモジュラー構造にあります。このセクションでは、これらが「ルーチンのライブラリ」と「パッケージ」を意味することを説明します(後者の場合、著者はAdaから取られた用語で、この機能を持つ他の言語(CLUのクラスターとModulaのモジュール)について言及しています)。

考えてみれば、これらのアプローチはいずれも、オープン/クローズの原則に準拠するコードの作成を支援することを目的としていませんでした。これは著者を彼らの幾分時期尚早な評価に導くかもしれないが、それは後に第2版で修正された。


第一版と第二版の間に具体的に著者がその発言について考えを変えたのは、本の中で、つまりパートF:さまざまな言語でのメソッドの適用と環境 "。この章では、著者はオブジェクト指向メソッドを古い言語で使用する方法について説明します。

Fortranのような古典的な言語はまったくO-Oではありませんが、それらをまだ使用しなければならない人々は...これらの古いアプローチの制限内で可能な限り多くのO-Oのアイデアを適用したいと思うかもしれません。

特に、この部分では、Meyerが、CやFortranでさえ継承を実装する方法(いくつかの注意点と制限がありますが、それでも)をどのようにして実現できるかを詳しく説明しています。

ご覧のとおり、これは本当にその声明を初版から改訂することを求めています。どのように正確にそれを行うかについての現実的な例で「古典的なアプローチで...方法はありません」を調整する方法を説明することは、実際には不可能であるように見えますcan.

18
gnat