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


10

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

この定数を修正する行為は、クラスを変更して閉じる必要があると仮定しているため、Open-Closed Principleの違反を示していますか?


10
現実の世界が変化するため、ソフトウェアも変化します。一方、税率を一定にすることは、オープンクローズドプリンシプルに違反することにはなりません。税率は、実行時にバインドする必要がある明白な変更可能なアイテムです。
Richard Chambers

4
私はリチャードに完全に同意します。この「定数」を修正するためにコードを変更する必要がある場合は、OCPが問題の最小です。
Robert Harvey

3
OCPの違反を構成するものは非常に主観的であり、すべてがとにかく少し時代遅れです(実装の継承はもはやベストプラクティスではないため)。これは典型的な質問であり、質問をしている人の考えを推測する必要があります。
RobertBräutigam17年

2
@DocBrown:「新しい要件」とは何ですか?あなたは私にいくつかのコードを見せてくれます、OCPがあなたがそれをどのように準拠しているかに関係なく、コードを変更することを間違いなく必要とする新しい要件を指摘できます。したがって、質問に戻ります。開発者がビジネスエキスパートに質問し、税率が2、3年に1回以上変化することを期待していなかった場合、構成可能または注入可能にしても意味がありません。単純にして、知っていることを準備してください。そして、これらのことについては、クラスの外部にしてください。したがって、状況によって異なります。
RobertBräutigam17年

1
@RobertBräutigam:私の要点は、「OCP準拠」などのIMHOはなく、「要件の特定のカテゴリのコンテキストでOCP準拠」しかないことです。確かに、コンポーネントが「OCP準拠」である必要のあるカテゴリーには主観があり得ます。しかし、この質問で説明されているケースでは、私が理解しているように、変化する要件がすでに特定されているため、この「所得計算クラス」は明らかにこの特定の要件のコンテキストでOCPに従いません。
Doc Brown

回答:


14

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

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

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

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

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

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

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

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

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

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


OK、OCPは、さまざまなユースケースに拡張可能な動作を提供するためのものであり、リストに挙げた3つの方法のいずれかを使用します。しかし、もしOPの例が基本的な何かが変化しようとしていることを暗示しているとしたらどうでしょう?OPの出身国はわかりませんが、私の国では税率はあまり変わりません。これは悪い例ですが、要点を強調するために、定数で意図的に抽出されたのかもしれません。私はそれが構成可能または拡張可能であることを意図されていなかったと確信しています。だからおそらく「ベンダーAによるソースコードの変更を禁止することとは何の関係もない」という質問があったのかもしれません。
Vadim Samokhin 2017

少なくともそのように理解しました。彼の受け入れられた答えを削除した貧しい男はそうしたのかもしれません。あなたは少し違う角度からそれを見てきました-私はあなたの要点を理解し、それに同意します。しかし、最も賢明なコメントは@RobertBräutigamによって与えられたようです。今まで、OCPが主観的であることを理解していませんでした。
Vadim Samokhin 2017

1
私が同じ質問をされたことがあるとしたら、返事として尋ねるべき質問が1つあります。「その動作は、何らかの形で拡張または構成されているはずですか?」はいの場合-クラス自体を直接変更することはOCPの違反です。ない場合-OCPは単にその状況では適用されません。
Vadim Samokhin 2017

1
@Zapadlo:コンポーネントが要件のクラスの OCP 満たしているかどうかはあまり主観的ではないと思います-ほとんどの場合、新しい要件がコンポーネントのソースコードの変更を必要とするか、またはコンポーネントがこの要件をサポートするかは明らかです。」可能なアプローチは、私の編集を参照してください、それは私がリストされた最初の3つの手段に限定されるものではない実装するOCPがちょうど誤解を招く名前があり、かなり悪いが、教科書の多くで説明しているので、主観性のあなたの概念が発生する可能性があります。。
ドキュメントをブラウン

私の主観性の概念は、私があなたの言ったことを完全には理解していなかったという事実によって引き起こされましたが、今はそうだと思います。洞察に満ちたコメントと回答に感謝します。
Vadim Samokhin 2017

4

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

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

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

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

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

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

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


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


1
問題は、税率のようなものをコードに埋め込むのが悪い考えであるかどうかではなく、ここ(OPを含む)のほとんどの人にとって明白であることは確かです。問題は、「これはOCPに違反しているか」ということでした。だから私はあなたの答えがこの質問をどのように参照しているかはわかりません。
Doc Brown、

1

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

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

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


0

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


-2

私がそれを見る方法は、オープンクローズド原則の違反ではありません。ただし、時間の経過に伴って変化するもの(税率など)が定数であるという事実は設計上の欠陥です。定数の値を変更するのではなく、税率の処理方法を変更する必要があります。これは、全体を再コンパイルせずに変更できる設定のタイプである必要があります。


「設計上の欠陥」は、定数を変更するためにコードを再コンパイルする必要があるため、オープンクローズの原則に違反しているということですか。
Erdrik Ironrose
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.