2

設計で直面している問題と非常によく似ているため、さまざまな形式の実数を検証する問題を検討しています。

実数は、さまざまな形式の組み合わせで提供されます。たとえば、次のようになります。1.先頭に符号がある/ない2.小数点がある/ない(小数点がない場合は、小数点以下の桁数を事前に合意できます)3.基数10またはベース16

各組み合わせを許可する必要があるため、2x2x2=8の組み合わせがあります。新しい条件が課されるたびに、複雑さが指数関数的に増加することがわかります。

オブジェクト指向デザインでは、通常、数値形式ごとにクラスを割り当て(たとえば、この場合は8つのクラスがあります)、各クラスには個別の検証関数があります。ただし、新しい条件ごとに、必要なクラスの数を2倍にする必要があり、すぐに悪夢になります。

手続き型プログラミングでは、3つのフラグ(つまり、has_sign、has_decimal_point、number_base)を使用して、検証する実数のプロパティを識別します。検証用の単一の関数があります。そこでは、フラグを使用してその動作を制御します。


// This is part of the validation function

if (has_sign) check_sign();

for (int i = 0; i < len; i++) { if (has_decimal_point) // Check if number[i] is '.' and do something if it is. If not, continue

if (number_base = BASE10)
    // number[i] must be between 0-9
else if (number_base = BASE16)
    // number[i] must be between 0-9, A-F

}

繰り返しになりますが、関数がifステートメントとフラグで雑然となると、複雑さはすぐに手に負えなくなります。

私はあなたが以前にこの性質の設計問題に出くわしたと確信しています-振る舞いの違いをもたらす多くの独立した違い。コードを完全に保守不可能にすることなく、どのようにしてソリューションを実装できたのか、非常に興味があります。

ブリッジパターンのようなものが役に立ちましたか?

4

5 に答える 5

4

オブジェクト指向の設計では、通常、数値形式ごとにクラスを割り当て (たとえば、この場合は 8 つのクラスがあります)、各クラスには個別の検証関数があります。

いやいやいやいやいや。せいぜい、数値入力を表すためのタイプを持っているでしょう(そうでStringない場合に備えて)。もう 1 つは実数用です (ほとんどの言語では組み込み型を選択しますが、とにかく)。数値入力を受け取り、それを実数に変換する知識を持つParserクラス。

より一般的に言えば、動作の 1 つの違い自体が、1 つのクラスに自動的にマップされるわけではありません。クラス内のプロパティにすることもできます。最も重要なことは、動作を直交的に扱う必要があることです。

(独自のパーサーを作成することを想像して) 符号があるかどうか、小数点があるかどうか、16 進数かどうかを考えると、複雑さの 3 つの独立したソースがあり、どこかに 3 つのコードを見つけても問題ありません。それぞれこれらの問題の 1 つを扱います。しかし、明示的な方法でさまざまな組み合わせを処理する 2^3 = 8 個の異なるコードをどこでも見つけることはできません。

新しい選択肢を追加すると想像してください。突然、数字に「e」が含まれている可能性があることを思い出し (2.34e10 など)、それをサポートできるようにしたいとします。直交戦略を使用すると、もう 1 つの独立した複雑性の原因、つまり 4 つ目のソースができます。あなたの作戦で8ケースが一気に16ケースに!明らかにノーノー。

于 2009-06-30T09:58:20.167 に答える
2

OOソリューションに各番号パターンのクラスが含まれるとあなたが考える理由はわかりません。私のOOソリューションは、正規表現クラスを使用することです。また、手続き型の場合は、おそらく標準ライブラリのstrtod()関数を使用します。

于 2009-06-30T09:49:56.983 に答える
2

あなたはパーサーを求めています、それを使用してください:

また: http://en.wikipedia.org/wiki/Parser_generator

では、この種の問題の複雑さをどのように処理すればよいでしょうか? できれば、再定式化します。

あなたの場合、パーサー ジェネレーター (または正規表現) を使用することは、扱っている問題により適した言語である DSL (ドメイン固有言語) を使用することです。

設計パターンと OOP は便利ですが、すべての問題に対する最善の解決策ではありません。

于 2009-06-30T09:53:07.243 に答える
0

申し訳ありませんが、私はvbを使用しているので、私がしているのは基本関数であり、評価関数を組み合わせているので、私が行った方法で偽のコードを作成します

function getrealnumber(number as int){ return  getrealnumber(number.tostring) }
function getrealnumber(number as float){ return  getrealnumber(number.tostring) }
function getrealnumber(number as double){ return  getrealnumber(number.tostring) }
function getrealnumber(number as string){
if ishex(){ return evaluation()}
   if issigned(){ return evaluation()}
   if isdecimal(){ return evaluation()}
 }

バイナリと8進数を実行する方法を理解するのはあなた次第です

于 2009-06-30T09:56:32.790 に答える
0

ハンマーでハエを殺すことはありません。

あなたの問題にオブジェクト指向ソリューションを使用することは、極端にやり過ぎだと本当に感じています。オブジェクト指向ソリューションを設計できるからといって、すべての問題にそのようなソリューションを強制する必要があるわけではありません。

私の経験から、問題に対する OOD の解決策を見つけるのが困難な場合は、ほとんどの場合、OOD が適切でないことを意味します。OOD は単なるツールであり、神そのものではありません。あなたが提示したような問題ではなく、大規模な問題を解決するために使用する必要があります。

したがって、実際の答えを得るには(上記の誰かのように):正規表現を使用してください。それを超えるすべてのソリューションは、やり過ぎです。

OODソリューションの使用を主張する場合....まあ、あなたが提示したすべてのフォーマットは互いに直交しているため、可能なすべての組み合わせに対してクラスを作成する必要はないと思います。形式ごとにクラスを作成し、入力を各 に渡します。その場合、複雑さは直線的に増加します。

于 2009-06-30T10:35:43.227 に答える