特定のプログラム用のインターフェイスを作成しようとすると、通常、検証されていない入力に依存する例外をスローしないようにします。
よくあることは、次のようなコードを考えたことです(これは単なる例であり、実行する機能は気にしないでください(Javaの例))。
public static String padToEvenOriginal(int evenSize, String string) {
if (evenSize % 2 == 1) {
throw new IllegalArgumentException("evenSize argument is not even");
}
if (string.length() >= evenSize) {
return string;
}
StringBuilder sb = new StringBuilder(evenSize);
sb.append(string);
for (int i = string.length(); i < evenSize; i++) {
sb.append(' ');
}
return sb.toString();
}
OK、だからそれevenSize
は実際にユーザー入力から派生したと言う。それで、私はそれが均一であるかどうかわかりません。しかし、例外がスローされる可能性があるこのメソッドを呼び出したくありません。そこで、次の関数を作成します。
public static boolean isEven(int evenSize) {
return evenSize % 2 == 0;
}
しかし、今では同じ入力検証を実行する2つのチェックがあります。if
ステートメント内の式との明示的なチェックですisEven
。コードが重複しているため、見栄えがよくないため、リファクタリングしましょう。
public static String padToEvenWithIsEven(int evenSize, String string) {
if (!isEven(evenSize)) { // to avoid duplicate code
throw new IllegalArgumentException("evenSize argument is not even");
}
if (string.length() >= evenSize) {
return string;
}
StringBuilder sb = new StringBuilder(evenSize);
sb.append(string);
for (int i = string.length(); i < evenSize; i++) {
sb.append(' ');
}
return sb.toString();
}
OK、それで解決しましたが、今は次のような状況になります。
String test = "123";
int size;
do {
size = getSizeFromInput();
} while (!isEven(size)); // checks if it is even
String evenTest = padToEvenWithIsEven(size, test);
System.out.println(evenTest); // checks if it is even (redundant)
冗長なチェックが行われました。値が偶数であることは既にわかっていますが、padToEvenWithIsEven
この関数を呼び出したときに常にtrueを返すパラメーターチェックを実行します。
今のisEven
コースの問題を提起しませんが、パラメータのチェックが面倒であれば、これはあまりにも多くの費用が発生する場合があります。それに加えて、冗長な呼び出しを実行することは、単に正しくないと感じます。
「検証済みの型」を導入するか、この問題が発生しない関数を作成することにより、この問題を回避できる場合があります。
public static String padToEvenSmarter(int numberOfBigrams, String string) {
int size = numberOfBigrams * 2;
if (string.length() >= size) {
return string;
}
StringBuilder sb = new StringBuilder(size);
sb.append(string);
for (int i = string.length(); i < size; i++) {
sb.append('x');
}
return sb.toString();
}
しかし、これにはスマートな思考とかなり大きなリファクタリングが必要です。
isEven
二重のパラメータチェックを繰り返し実行することを回避できる(より)一般的な方法はありますか?padToEven
無効なパラメーターを実際に呼び出して例外をトリガーしないようにしたいのですが。
例外なく、例外のないプログラミングを意味するわけではありません。ユーザー入力は設計によって例外をトリガーしませんが、ジェネリック関数自体にはまだパラメーターチェックが含まれています(プログラミングエラーから保護する場合のみ)。
padToEvenWithIsEven
しないことを覚えておく必要があります。入力の有効性チェックを実行して、呼び出しコードのプログラミングエラーから自身を保護します。この検証がどの程度必要かは、呼び出しコードを書いている人が間違ったパラメータを渡すリスクに対してチェックのコストをかけるコスト/リスク分析に依存します。