タグ付けされた質問 「open-close」

8
LSP vs OCP / Liskov Substitution VS Open Close
私は、OOPの固い原則を理解しようとしていますが、LSPとOCPにはいくつかの類似点があるという結論に達しました(詳しくは言いませんが)。 オープン/クローズの原則には、「ソフトウェアエンティティ(クラス、モジュール、関数など)は拡張のために開かれているが、変更のために閉じられている必要があります」と記述されています。 簡単な言葉で言えば、LSPはのFooインスタンスをBar派生元のインスタンスに置き換えることができFoo、プログラムはまったく同じように機能することを示しています。 私はプロのOOPプログラマーではありませんが、LSPはBar、から派生しFooたものがその中の何も変更せず、拡張する場合にのみ可能であるように思われます。つまり、特定のプログラムのLSPはOCPが真の場合にのみ真であり、OCPはLSPが真の場合にのみ真です。それは、それらが等しいことを意味します。 私が間違っている場合は修正してください。これらのアイデアを本当に理解したいです。答えてくれてありがとう。

8
Object.finalize()のオーバーライドは本当に悪いですか?
オーバーライドに対する主な2つの引数Object.finalize()は次のとおりです。 いつ呼び出されるかを決めることはできません。 まったく呼び出されない場合があります。 私がこれを正しく理解していれば、Object.finalize()それがそんなに嫌いな十分な理由だとは思いません。 オブジェクトの割り当てを解除する適切なタイミングは開発者ではなく、VM実装とGCが決定します。いつObject.finalize()呼び出されるかを決めることが重要なのはなぜですか? 通常、私が間違っている場合は修正Object.finalize()しますが、GCが実行される前にアプリケーションが終了したときのみ呼び出されません。ただし、アプリケーションのプロセスが終了すると、オブジェクトは解放されます。だから、Object.finalize()それが呼び出される必要はなかったので、呼び出されませんでした。開発者が気にするのはなぜですか? 手動で閉じる必要のあるオブジェクト(ファイルハンドルや接続など)を使用するたびに、非常にイライラします。オブジェクトにの実装があるかどうかを常に確認する必要がありclose()、過去のある時点でいくつかの呼び出しを逃したと確信しています。close()実装を入れることでこれらのオブジェクトを破棄するためにVMとGCに任せる方が単純で安全ではないのはなぜObject.finalize()ですか?

1
(/ did)Bertrand Meyerは、サブクラス化が「閉じた」モジュールを拡張する唯一の方法だと考えるのはなぜですか?
MeyerのObject-Oriented Software Construction(1988)で、彼は次のようにオープン/クローズド原則を定義しています。 モジュールがまだ拡張可能であれば、モジュールは開いていると言われます。たとえば、フィールドに含まれるデータ構造にフィールドを追加したり、実行する一連の機能に新しい要素を追加したりすることができます。 モジュールは、他のモジュールで使用できる場合、閉じられていると言われます。これは、モジュールに明確に定義された安定した説明(情報隠蔽という意味でのインターフェース)が与えられていることを前提としています。 彼は言い​​続けます: モジュールを再度開く場合、古いバージョンに依存しているため、すべてのクライアントを再度開いて更新する必要があります。…[この問題]は、モジュールを新しい関数またはデータ要素によって拡張する必要があるたびに発生し、直接および間接クライアントの変更をトリガーします。...設計とプログラミングに対する古典的なアプローチでは、オープンとクローズの両方のモジュールを記述する方法はありません。 このジレンマに対するMeyerの解決策は、既存のクラスを変更してライブラリモジュールを拡張しないことです。代わりに、既存のクラスをサブクラス化する新しいモジュールを作成し、新しいクライアントがその新しいモジュールに依存するようにします。 今、1988年に、私はTurbo PascalとBlankenship Basicでおもちゃ(手続き)プログラムを書いていました、そして、21世紀の専門的な経験はJVM、CLR、および動的言語でしたので、Meyerの意味がわかりません「設計とプログラミングへの古典的なアプローチ」による。 Meyerのクライアントモジュールを再度開く必要がある理由の具体例(より多くのケースを必要とする、より多くのメンバーを含む列挙のswitchステートメント)は十分に合理的なようですが、ライブラリに機能を追加するたびにアサーションを正当化することはほとんどありませんモジュール、すべてのクライアントを更新する必要があります。 この主張が1988年に自明であると思われる歴史的な理由はありますか?たとえば、C静的ライブラリに関数またはデータ構造を追加すると、下位互換性のあるAPIでもクライアントを再コンパイルする必要があるようにレイアウトが変更されましたか?または、MeyerはAPIの下位互換性を強制するメカニズムについて本当に話しているだけですか?

4
モックはオープン/クローズの原則に違反しますか?
少し前に、私は見つけることができないStack Overflowの回答で、パブリックAPIをテストする必要があることを説明した文を読み、著者はインターフェイスをテストする必要があると言いました。また、メソッドの実装が変更された場合、テストケースを変更する必要はありません。これを行うと、テスト中のシステムが機能することを確認する契約が破られるため、著者は説明しました。つまり、メソッドが機能しない場合はテストが失敗しますが、実装が変更されたためではありません。 私たちがock笑について話すとき、これは私の注意を呼びました。モックはテスト対象システムの依存関係からの期待呼び出しに大きく依存しているため、モックはインターフェイスではなく実装と密接に結合されています。 モックとスタブの調査中、いくつかの記事は、依存関係からの期待に依存しないため、モックの代わりにスタブを使用する必要があることに同意しています。 私の質問は次のとおりです。 モックはオープン/クローズの原則に違反しますか? 最後の段落のスタブを支持する議論に欠けているものはありますか? もしそうなら、いつスモックを作成するのに適したユースケースになり、スタブを使用するのに適したユースケースになりますか?

5
オーバーロードは、オープン/クローズの原則の例ですか?
ウィキペディアによると 「ソフトウェアエンティティ(クラス、モジュール、関数など)は拡張のために開かれている必要がありますが、変更のために閉じられている必要があります」 関数という言葉が目を引きましたが、メソッドのオーバーロードを作成することは、オープン/クローズの原則の一例とみなすことができると思いますか? 例を説明しましょう。サービスレイヤーにメソッドがあり、ほぼ1000か所で使用されていることを考慮してください。メソッドはuserIdを取得し、ユーザーが管理者であるかどうかを判断します。 bool IsAdmin(userId) ここで、userIdではなくユーザー名に基づいて、ユーザーが管理者であるかどうかを判断する必要があると考えてください。上記のメソッドのシグネチャを変更すると、1000箇所でコードが破損します(関数は修正のために閉じる必要があります)。したがって、ユーザー名を取得するオーバーロードを作成し、ユーザー名に基づいてuserIdを見つけ、元のメソッドを見つけることができます。 public bool IsAdmin(string username) { int userId = UserManager.GetUser(username).Id; return IsAdmin(userId); } このように、オーバーロードを作成して機能を拡張しました(機能は拡張に対して開かれている必要があります)。 それはオープン/クローズド原則の例ですか?

7
リファクタリングとオープン/クローズの原則
最近、きれいなコード開発に関するWebサイトを読んでいます(英語ではないため、ここにはリンクを入れません)。 このサイトで宣伝されている原則の1つは、オープンクローズド原則です。各ソフトウェアコンポーネントは、拡張用にオープンにし、変更用にクローズする必要があります。たとえば、クラスを実装してテストした場合、バグを修正するか、新しい機能を追加する(たとえば、既存のメソッドに影響を与えない新しいメソッド)ためにクラスを変更するだけです。既存の機能と実装は変更しないでください。 通常、インターフェイスIと対応する実装クラスを定義することにより、この原則を適用しますA。クラスAが安定(実装およびテスト)になったとき、通常はあまり変更しません(おそらく、まったく変更しません)。 コードに大きな変更を必要とする新しい要件(パフォーマンス、インターフェイスのまったく新しい実装など)が到着した場合、新しい実装を作成し、成熟していない限りB使用Aし続けBます。B成熟したときに必要なのは、Iインスタンス化の方法を変更することだけです。 新しい要件がインターフェースの変更も示唆している場合、新しいインターフェースI'と新しい実装を定義しますA'。ですからI、A凍結しており、残る実装限りとして生産システムのためI'およびA'それらを交換するのに十分安定していません。 そのため、これらの観察を考慮して、Webページが複雑なリファクタリングの使用を提案していることに少し驚いていました。 オープン/クローズド原則の実施と、ベストプラクティスとしての複雑なリファクタリングの使用の提案との間に矛盾や矛盾はありませんか?または、ここでのアイデアは、クラスの開発中に複雑なリファクタリングを使用できるということですAが、そのクラスが正常にテストされたら、凍結する必要がありますか?

2
このクラスを開閉するのが難しい
これが私の問題です。ゲームパッド、よくレースする、ジョイスティックなど、さまざまなHIDデバイスからの入力を読みたいのですが、ほとんどすべてのゲームコントローラです。問題は、それらすべてに異なる入力があることです。 ゲームパッドにはボタン、スイッチ、スティックがあり、レースウェルにはギアスティックが付いている場合があります。これらのさまざまなコンポーネントをすべて3つに抽象化して、可能なすべての組み合わせを持つ基本クラスを作成するのではなく、 abstract class Device { public Buttons Buttons; public Axes Axes; public Switches Switches; public GearSticks GearSticks; //many more } 私は今持つことができます: abstract class Device { public Buttons Buttons; //on or off public Axes Axes; //range [-100%:100%] public Switches Switches; //multiple states } すべての入力を3種類に抽象化できるため、すべての具体的な実装を介して拡張に対して開かれている間、クラスを閉じたままにできるため、最初はこれに満足しました。 しかしその後、私は自分自身にかかわらず、私は避けられないが遅延していた場合にどのような?ある日Deviceクラスに別のフィールドを追加する必要がある場合はどうなりますか?トラックボールのようなものはサポートしていません! このクラスを将来証明できる方法はありますか?私がそれを見る方法では、私はこのようなものになるでしょう: public Device1 : Device …

5
設計パターンのオープンクローズの原則
オープンクローズの原則を実際にどのように適用できるかについて、少し混乱しています。時間の経過とともにビジネスの要件は変化します。Open-Closedの原則に従って、既存のクラスを変更する代わりにクラスを拡張する必要があります。クラスを延長するたびに、要件を満たすのは現実的ではないように思えます。列車予約システムの例を挙げましょう。 列車予約システムでは、チケットオブジェクトがあります。通常のチケット、割引チケットなど、さまざまなタイプのチケットが存在する可能性があります。チケットは抽象クラスで、RegularTicketとConcessionTicketsは具象クラスです。すべてのチケットには共通のPrintTicketメソッドがあるため、基本抽象クラスであるチケットで記述されます。これが数か月間うまくいったとしましょう。ここで、チケットのフォーマットを変更するように要求する新しい要件が発生します。印刷されたチケットにいくつかのフィールドが追加されるか、形式が変更される場合があります。この要件を満たすために、次のオプションがあります チケット抽象クラスのPrintTicket()メソッドを変更します。しかし、これは開閉原理に違反します。 子クラスのPrintTicket()メソッドをオーバーライドしますが、これは印刷ロジックを複製します。これは、DRY(自分を繰り返さないでください)の原則に違反しています。 だから質問は オープン/クローズの原則に違反せずに、上記のビジネス要件を満たすにはどうすればよいですか。 クラスが変更のために閉じられることになっているとき?クラスが変更のために閉鎖されていると見なすための基準は何ですか?それは、クラスの初期実装後ですか、それとも本番環境での最初のデプロイメント後か、それとも別の場合があります。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.