私は労働者の純年収を計算するクラスを持っています。税率を表す定数があります。しかし、ある日、税率が変更されたため、コードを修正する必要があります。
この定数を修正する行為は、クラスを変更して閉じる必要があると仮定しているため、Open-Closed Principleの違反を示していますか?
私は労働者の純年収を計算するクラスを持っています。税率を表す定数があります。しかし、ある日、税率が変更されたため、コードを修正する必要があります。
この定数を修正する行為は、クラスを変更して閉じる必要があると仮定しているため、Open-Closed Principleの違反を示していますか?
回答:
OCPは、ユーザーB、C、およびDによる使用のために、ある種のブラックボックスライブラリでベンダーAによって提供されるクラスまたはコンポーネントを考えると、よりよく理解できます(これは、明確にするために使用しているメンタルモデルにすぎないことに注意してください。クラスの唯一のユーザーが実際にAであるかどうかは問題ではありません)。
B、C、およびDが、ライブラリのソースコードを変更する必要なく、提供されたクラスをさまざまなユースケースに使用または再利用できる場合、コンポーネントはOCPを満たします(ユースケースのカテゴリに関して)。これを達成するためのさまざまな方法があります。
クラスを継承可能にする(通常、テンプレートメソッドパターンまたは戦略パターンと組み合わせて)
依存性注入のための「注入ポイント」を提供することにより
クラスまたはコンポーネントの構成パラメーターを提供することにより(例えば、あなたの場合のように、コンストラクター・パラメーター「税率」を使用することによって、または他の何らかの構成メカニズムを使用することによって)
プログラミング言語またはエコシステムに応じて、おそらく他の手段
教科書に見られる典型的な例は、多くの場合、最初のタイプまたは2番目のタイプです(これらの本の著者の目には、3番目のタイプは、あまりにも簡単すぎて言及する価値がないためです)。
ご覧のとおり、これはOCPとはまったく関係のない、ベンダーAによるソースコードの変更(バグ修正、最適化、または下位互換性のある方法での新機能の追加など)を禁止することとは関係ありません。OCPは、Aがライブラリーのコンポーネントとコンポーネントの細分性をどのように設計するかに関するものであるため、異なる再利用シナリオ(異なる税率での再利用など)が自動的に変更の要件を引き起こすことはありません。
したがって、他の人がここであなたに言われたことにもかかわらず、答えは明らかに「はい」であり、それはOCPの違反になります。
編集:誰かが正確なこのトピックについて詳細なブログ投稿を書いた間にあるようです。(Derek Elkinsが指摘したように)その一部はより適切に表現されているかもしれませんが、「OCPを満たすこと」は絶対的な特性ではなく、特定の状況でのみ評価できるものであるという筆者の見解を一般的に共有しているようです要件変更のカテゴリ。
他の人が言っているように、理想的には労働者所得クラスは定数のパラメーター化を可能にし、このクラスをその値から独立させます。
最終的に、呼び出し側のアプリケーションは、外部構成(ファイルなど)の観点からパラメーター化も可能にする場合があります。外部構成を作成したら、税率を変更できます。ただし、起動時に構成ファイルを1回だけ読み取る場合は、更新された税率を有効にするためにアプリケーションを再起動する必要があるため、これを維持する必要があります。マインド。指示されたときに構成を再読み取りするアプリケーション機能を提供することも、構成ファイルが変更されたときに通知するより複雑なメカニズムを提供することもできます...
長期的には、税の問題は単なるパーセンテージ以上のものを必要とすることがあります。たとえば、ある日、税法はより複雑で、いくつかのパーセンテージといくつかの定数が必要です(たとえば、$ 10k未満の金額はX%で課税されますが、残りはY%で課税されます)。
これは基本的に、ここで問題となっているメインクラスが税を計算するための戦略オブジェクトを受け入れる戦略パターンの使用を示唆しています。
さまざまな戦略(および%と$定数)は構成ファイルから選択可能である必要があり、新しい戦略を追加するにはいくつかの新しいコードを追加する必要がありますが、必ずしも既存のコードを更新する必要はありません。
各戦略は、実際の税を計算する方法とともに、独自の外部構成引数を解析/解釈する方法を知っている場合があります。
動的に、税は支配するロケールにさらに依存する可能性があるため、収益または従業員(またはその両方)に関連付けられたロケールがある場合があります。外部構成では、ロケールを税戦略に関連付ける場合があります。
これらを明示的に管理する依存性注入も参照してください。
税額を変更するためにクラスを変更する必要がある場合、その設計は実際にOCPに違反しています。これまで説明してきたことに対する適切な設計は、電卓クラスが税額をパラメーターとして受け取ることです。
クラスがインスタンス化されている(つまり、静的クラスではない)場合、その値がコンストラクターを通じて注入される税変数クラスプロパティを作成することにより、クラスの凝集度も向上します。
要するに、現在の設計では、クラスは実際には定数ではない定数値に依存します(定数は、PIの値のように、決して変化しない値として定義します)。OCPに違反しています。コンストラクター引数として税額を受け取るようにデザインを変更します。
@Becuzzに完全に同意し、私はこれを要約したいだけです。OCPは、クラスに注入される再利用された(したがって、有用な)抽象化を見つけることです。したがって、クラスの動作は、コードを変更することによってではなく、異なる実装を提供することによって変更されます。これは、ロバートマーティンの著書「アジャイルソフトウェア開発、原則、パターン、および実践」で非常に明確になっています。対応する章「オープンクローズの原則」、「抽象化が鍵」を参照してください。継承によってのみ動作を変更できるという別の誤解を明らかにします。Robert Martinではなく、1988年に彼の著書「Object Oriented Software Construction」でそれを提案したのはBertrand Meyerでした。
私がそれを見る方法は、オープンクローズド原則の違反ではありません。ただし、時間の経過に伴って変化するもの(税率など)が定数であるという事実は設計上の欠陥です。定数の値を変更するのではなく、税率の処理方法を変更する必要があります。これは、全体を再コンパイルせずに変更できる設定のタイプである必要があります。