問題タブ [open-closed-principle]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
oop - オープン/クローズド原則の背後にある意味と理由は何ですか?
オープン/クローズの原則では、ソフトウェア エンティティ (クラス、モジュールなど) は拡張に対してオープンである必要がありますが、変更に対してはクローズされている必要があります。これは何を意味し、なぜそれが優れたオブジェクト指向設計の重要な原則なのですか?
language-agnostic - オブジェクト指向デザイン、オープン/クローズド原則の質問
私はこのオブジェクト指向の設計の質問についてしばらく考えていましたが、満足のいく解決策を思い付くことができなかったので、ここの群衆にいくつかの意見を公開したいと思いました。
ターン制のボードゲームを表すゲームクラスがあります。この質問の目的では、モノポリーに似ていると想定できます。私のデザインには、TakeTurnメソッドを含むPlayerクラスがあります。
ゲームはすべてのプレイヤーをループし、TakeTurnメソッドを呼び出して、ターンを完了するために必要なすべてのことを行います。n人のプレイヤーがいて、任意の人数をコンピュータープレイヤーに設定できるようにしたいと思っています。ですから、私の考えは、HumanPlayerクラスとComputerPlayerクラスがあり、どちらもPlayerから派生しているということでした。
ゲームはPlayerクラスのみを認識し、各PlayerでTakeTurnメソッドを順番に呼び出すだけです。私の問題は、ComputerPlayerオブジェクトを完全に自動化できるという事実にあります。つまり、独占の例を維持すると、ロジックの一部を使用してプロパティを購入することを決定できます。ここで、HumanPlayerオブジェクトを使用すると、たとえばプロパティを購入できるようにするために、実際のユーザーから入力を取得する必要があります。これは、異なるインターフェイスを意味し、派生してはならないことを意味する可能性があります。
GameクラスにさまざまなPlayerクラスの実際の実装を明示的に知らない限り、問題の適切な解決策を思いつくことはできませんでした。ゲームクラスでは、人間とコンピューターのプレーヤーだけが存在し、拡張のために効果的に閉じると常に想定できましたが、オブジェクト指向プログラミングとしては適切ではないようです。
これについてのご意見をいただければ幸いです。
c++ - 来客パターン+オープン・クローズ原則
Open/Closed Principleを尊重してVisitor パターンを実装することは可能ですが、新しい訪問可能なクラスを追加することはできますか?
オープン/クローズの原則では、「ソフトウェア エンティティ (クラス、モジュール、関数など) は、拡張に対してオープンである必要がありますが、変更に対してクローズされている必要があります」と述べています。
AbstractVisitor から派生する任意の数のクラスを実装できます。これは拡張可能です。AbstractVisitor から派生したクラスはコンパイルされないため、新しい訪問可能なクラスを追加することはできません。変更のために閉じられました。
AbstractVisitor クラス ツリーは、Open/Closed Principle を尊重します。AbstractVisitable クラス ツリーは、拡張できないため、Open/Closed Principle を尊重しません。
以下のように AbstractVisitor と AbstractVisitable を拡張する以外の解決策はありますか?
dependency-injection - クラスを OCP に準拠させる - 関数をオブジェクトに因数分解する
私は常に追加しているクラスを持っています。
これらすべての新機能が追加されているため、このクラスは開閉式ではないことに気付きました。そこで、これらの関数を Request オブジェクトにカプセル化することで、この変更に対してこのクラスを閉じることを考えました。私は次のようなものになります:
これにより、 OrderRepository が拡張用に開かれ、変更用に閉じられます。ただし、これに関していくつかの問題にすぐに遭遇しました。
1.) リクエストが操作する必要があるデータは、ユーザー提供 (実行時) と依存性注入提供の両方です。明らかに、1 つのコンストラクターで両方を満たすことはできません。私はできません:
そしてそれを呼び出します。DIフレームワークがオブジェクトを「部分的に」構築し、残りは私に任せる方法が必要です。しかし、それを行う方法はありません。この概念を「変数コンストラクター インジェクション」と呼んだブログを見ました。
2.) 次に考えたのは、これを 2 つの別々のクラスに分割することでした。ユーザーは RequestContext を作成して入力し、それをリポジトリに渡します。リポジトリは、そこから RequestProcessor (より適切な名前を思いつきません) を作成します。私は次のことを考えました:
それは良い第一歩でした。ただし、リクエスト プロセッサには、保存している正確なタイプのコンテキストが必要ですが、ここにはありません。型の辞書を型に使用することもできますが、それは Open-Closed であるという目的を無効にします。そのため、次のようなことをしなければならなくなります。
これは奇妙で、私は通常、奇妙に繰り返されるテンプレート パターンが好きではありません。さらに、名前付けの問題かもしれませんが、ユーザーがコンテキストを埋めて、それをリクエストするように私に依頼するという考えは奇妙に思えます。
3.) 上記のすべてを取り除き、次のものを用意することを考えました:
これは悪くありませんが、API は醜いです。このオブジェクトのクライアントは、いわばそれを 2 回「構築」する必要があります。また、PackArgs を呼び出すのを忘れた場合は、何らかの例外をスローする必要があります。
続けることもできますが、これらは現時点で最も混乱している問題です。何か案は?
java - オープンクローズ原則とJavaの「最終」修飾子
オープンクローズの原則は、「ソフトウェアエンティティ(クラス、モジュール、関数など)は拡張のためにオープンである必要がありますが、変更のためにクローズされるべきである」と述べています。
ただし、彼の有名な著書「Effective Java」のジョシュア・ブロックは、「継承のための設計と文書化、またはそれを禁止する」というアドバイスを提供し、プログラマーに「final」修飾子を使用してサブクラス化を禁止するように勧めています。
これらの2つの原則は明らかに互いに矛盾していると思います(私は間違っていますか?)。コードを書くとき、どの原則に従いますか、そしてその理由は何ですか?クラスを開いたままにしますか、それらの一部(どのクラスですか?)の継承を禁止しますか、または可能な限り最後の修飾子を使用しますか?
design-patterns - デザイン パターン - 抽象ファクトリ パターンとオープン クローズド プリンシプル
デザインパターン初心者です。
Open-Closed Principleを維持しながら、Abstract Factory-パターンを使用しようとしています。
次のコードを見てください。
Abstract Factory パターンの例にできますか?
はいの場合、Open-Closed Principle の概念を組み込んでリファクタリングするにはどうすればよいですか?
oop - Agile Principles, Patterns, and Practices in C# のデータ アクセス部分 (SQL Server を使用) はいかがですか
次のようなデータ アクセス コードについてどう思いますか。
個人的には、このようなコード (「is」を使用して型を検出し、何をすべきかを決定する) はあまり気分が良くありませんが、作者の Robert Martin は、DAL だけなので問題ないと言っているので、OCP の少しの違反は許容できる。
あなたはどのように思いますか?
open-closed-principle - オープン/クローズの原則は良い考えですか?
この質問は、OCP とは何かに関するものではありません。また、単純な答えも求めていません。
だから、ここに私がこれを尋ねる理由があります。OCP は 80 年代後半に初めて説明されました。当時の考え方や文脈が反映されています。懸念事項は、ソース コードを変更して機能を追加または変更することは、コードが既にテストされて運用に投入された後で、リスクとコストがかかりすぎるということでした。そのため、既存のソース ファイルをできるだけ変更することを避け、サブクラス (拡張機能) の形でコードベースに追加するだけにするという考えがありました。
私が間違っているかもしれませんが、私の印象では、ネットワーク ベースのバージョン管理システム(VCS) は当時はあまり使用されていませんでした。ポイントは、VCS はソース コードの変更を管理するために不可欠であるということです。
リファクタリングのアイデアは、はるかに最近のものです。自動リファクタリング操作を可能にする洗練された IDE は、当時は確かに存在しませんでした。今日でも、多くの開発者は利用可能な最高のリファクタリング ツールを使用していません。ここでのポイントは、このような最新のツールを使用すると、開発者は文字どおり数千行のコードを安全に、数秒で変更できるということです。
最後に、今日、自動化された開発者テスト(ユニット/統合テスト) のアイデアが広まっています。それをサポートする多くの無料の洗練されたツールがあります。しかし、既存のコードをまったくまたはほとんど変更しない場合、大規模な自動テスト スイートを作成して維持することに何のメリットがあるでしょうか。OCP が要求する新しいコードは、新しいテストのみを必要とします。
では、今日の OCP は本当に理にかなっているのでしょうか? 私はそうは思わない。代わりに、新しい機能が新しいクラスを必要としない場合は、新しい機能を追加するときに既存のコードを変更することを実際に好みます。そうすることで、コードベースがよりシンプルで小さくなり、読みやすく理解しやすくなります。以前の機能が壊れるリスクは、VCS、リファクタリング ツール、および自動化されたテスト スイートによって管理されます。
open-closed-principle - アプリケーションの完全なユニットテストスイートがある場合でも、Open / Closed Principle(OCP)を適用する必要がありますか?
OCPに関するウィキペディアの記事は次のように述べています(私の強調):
...オープン/クローズドの原則では、「ソフトウェアエンティティ(クラス、モジュール、関数など)は拡張のために開いている必要がありますが、変更のために閉じている必要があります」と述べています...これは、ソースコードが変更さ れる実稼働環境で特に役立ちます。製品での使用を認定するために、コードレビュー、単体テスト、およびその他のそのような手順が必要になる場合があります。原則に従ったコードは、拡張しても変更されないため、そのような作業は必要ありません。
それで、自動化された単体テストがない場合、OCPは価値があると正しく読んでいますが、必ずしもある場合はそうではありませんか?それともウィキペディアの記事は間違っていますか?