Belirli bir program için bir arabirim oluşturmaya çalıştığımda genellikle doğrulanmamış girişe bağlı istisnalar atmaktan kaçınmaya çalışıyorum.
Yani sık sık böyle bir kod parçası düşündüm ki (bu sadece bir örnek uğruna bir örnek, gerçekleştirdiği işleve aldırma, örneğin 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();
}
Tamam, evenSize
aslında kullanıcı girişinden türetilmiş olduğunu söyleyin . Bu yüzden bile olduğundan emin değilim. Ancak bu yöntemi bir istisna oluşması ihtimaliyle çağırmak istemiyorum. Bu yüzden aşağıdaki işlevi yaparım:
public static boolean isEven(int evenSize) {
return evenSize % 2 == 0;
}
ama şimdi aynı giriş doğrulamasını gerçekleştiren iki kontrolüm var: ifadedeki if
ifade ve açık check-in isEven
. Yinelenen kod, hoş değil, bu yüzden yeniden düzenleyelim:
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();
}
Tamam, bu çözüldü, ama şimdi aşağıdaki duruma giriyoruz:
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)
artık yedekli bir kontrolümüz var: değerin eşit olduğunu zaten biliyoruz, ancak padToEvenWithIsEven
yine de bu işlevi çağırdığımız için her zaman true döndürecek parametre kontrolünü gerçekleştiriyoruz.
Şimdi isEven
elbette bir sorun oluşturmuyor, ancak parametre kontrolü daha hantalsa, bu çok fazla maliyete neden olabilir. Bunun yanı sıra, fazladan bir çağrı yapmak doğru gelmiyor.
Bazen "doğrulanmış bir tür" tanıtarak veya bu sorunun oluşamayacağı bir işlev oluşturarak bu sorunu çözebiliriz:
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();
}
ancak bu biraz akıllı düşünme ve oldukça büyük bir yeniden düzenleme gerektirir.
Gereksiz çağrıları önleyebilmemiz isEven
ve çift parametre kontrolü gerçekleştirebilmemiz için (daha fazla) genel bir yol var mı? Çözümün aslında padToEven
geçersiz bir parametre ile çağrılmamasını ve istisnayı tetiklemesini istiyorum.
İstisnalar dışında, istisnasız programlama anlamına gelmez, yani kullanıcı girişi tasarım tarafından bir istisna tetiklemez, genel fonksiyonun kendisi hala parametre kontrolünü içerir (sadece programlama hatalarına karşı korumak için).
padToEvenWithIsEven
yapmadığını hatırlamanız gerekir . Arama kodundaki programlama hatalarına karşı kendini korumak için girişinde bir geçerlilik kontrolü yapar . Bu doğrulamanın ne kadar kapsamlı olması gerektiği, arama maliyetini yazan kişinin yanlış parametrede geçme riskine karşı çek maliyetini koyduğunuz bir maliyet / risk analizine bağlıdır.