web-dev-qa-db-ja.com

実世界の値を表す定数を更新することは、開閉原理の違反ですか?

私は労働者の純年収を計算するクラスを持っています。税率を表す定数があります。しかし、ある日、税率が変わったので、コードを修正する必要があります。

この定数を修正する行為は、クラスが修正のために閉じられるべきであると仮定しているため、 Open-Closed Principle の違反を示していますか?

10

OCPは、ユーザーB、C、およびDが使用するために、ある種のブラックボックスライブラリでベンダーAによって提供されるクラスまたはコンポーネントを考えると、よりよく理解できます(これは、明確にするために使用しているメンタルモデルにすぎないことに注意してください。クラスの唯一のユーザーが実際にAであるかどうかは問題ではありません)。

B、C、およびDが、ライブラリのソースコードを変更することなく、提供されたクラスをさまざまなユースケースで使用または再利用できる場合、コンポーネントは使用のカテゴリに関してOCP()を満たしますケース)。これを達成するためのさまざまな手段があります。

  • クラスを継承可能にする(通常、テンプレートメソッドパターンまたは戦略パターンと組み合わせて)

  • 依存性注入のための「注入ポイント」を提供することにより

  • クラスまたはコンポーネントの構成パラメーターを提供することにより(例えば、あなたの場合のように、コンストラクター・パラメーター「税率」を使用することによって、または他の構成メカニズムを使用することによって)

  • プログラミング言語またはエコシステムに応じて、おそらく他の手段

教科書に見られる典型的な例は、多くの場合、最初のタイプまたは2番目のタイプです(これらの本の著者の目には、3番目のタイプは、あまりにも簡単すぎて言及する価値がないためです)。

ご覧のとおり、これはベンダーによるソースコードの変更の禁止とは関係ありませんA(バグ修正、最適化、追加など)下位互換性のある方法での新機能)、これはOCPとはまったく関係ありません。OCPは、Aがどのようにインターフェイスを設計し、lib内のコンポーネントの粒度を設計するかに関するものであるため、さまざまな再利用シナリオ(さまざまな税率での再利用など)変更の要件を自動的に引き起こさない。

したがって、ここで他の人があなたに言ったことにもかかわらず、答えは明らかに "はい"であり、OCPの違反になります。

編集:誰かの間にあるようです 詳細なブログ投稿を書きました このトピックについて正確です。 (Derek Elkinsが指摘したように)その一部はより適切に表現されている可能性がありますが、著者は一般的に、「OCPを満たすこと」は絶対的な性質ではなく、特定の状況でのみ評価できるものであるという私の見解を共有しているようです要件変更のカテゴリ。

14
Doc Brown

他の人が言っているように、理想的には労働者所得クラスは定数のパラメーター化を可能にし、このクラスをその値から独立させます。

最終的に、呼び出し側のアプリケーションでは、外部構成(ファイルなど)の観点からパラメーター化も可能になる場合があります。外部設定を作成したら、税率を変更できます。ただし、起動時に設定ファイルを1回だけ読み取る場合は、更新された税率を有効にするためにアプリケーションを再起動する必要があるため、これを維持する必要があります。マインド。指示されたときに構成を再読み取りするアプリケーション機能を提供することも、構成ファイルが変更されたときに通知するより複雑なメカニズムを提供することもできます...

長期的には、税の問題は単なるパーセンテージ以上のものを必要とすることがあります。たとえば、ある日、税法がより複雑になり、いくつかのパーセンテージといくつかの定数が必要になります(たとえば、$ 10k未満の金額はX%で課税されますが、残りはY%で課税されます)。

これは基本的に、ここで問題となっているメインクラスが税金を計算するための戦略オブジェクトを受け入れる戦略パターンの使用を提案しています。

さまざまな戦略(および%と$定数)は構成ファイルから選択可能である必要があり、新しい戦略を追加するにはいくつかの新しいコードを追加する必要がありますが、必ずしも既存のコードを更新する必要はありません。

各戦略は、実際の税を計算する方法とともに、独自の外部構成引数を解析/解釈する方法を知っている場合があります。

動的に、税は支配するロケールにさらに依存する可能性があるため、収益または従業員(またはその両方)に関連付けられたロケールがある場合があります。外部設定では、ロケールを税戦略に関連付ける場合があります。


依存性注入 も参照してください。これらはこれらを明示的に管理します。

4
Erik Eidt

税額を変更するためにクラスを変更する必要がある場合、その設計は実際にOCPに違反しています。これまで説明してきたことに対する適切な設計は、電卓クラスが税額をパラメーターとして受け取ることです。

クラスがインスタンス化されている場合(静的クラスではないことを意味します)、その値がコンストラクターを通じて注入される税変数クラスプロパティを作成することにより、クラスの凝集度も向上します。

要するに、現在の設計では、クラスを実際には定数ではない定数値に依存させます(定数は、PIの値のように、決して変化しない値として定義します)。 OCPに違反しています。コンストラクター引数として税額を受け取るようにデザインを変更します。

@Becuzzに完全に同意し、私はこれを要約したいだけです。OCPは、クラスに注入される再利用された(したがって、有用な)抽象化を見つけることです。したがって、クラスの動作は、コードを変更することによってではなく、異なる実装を提供することによって変更されます。これは、Robert Martinの本「 アジャイルソフトウェア開発、原則、パターン、および実践 」で非常に明確になっています。対応する章「オープン/クローズの原則」、「抽象化が鍵」を確認してください。動作は継承によってのみ変更できるという別の誤解を明らかにします。 1988年に彼の本「 オブジェクト指向ソフトウェア構築 」でそれを提案したのはベルトランマイヤーであり、ロバートマーティンではありませんでした。

0
Zapadlo