เมื่อฉันพยายามสร้างส่วนต่อประสานสำหรับโปรแกรมเฉพาะฉันมักจะพยายามหลีกเลี่ยงการโยนข้อยกเว้นที่ขึ้นอยู่กับอินพุตที่ไม่ผ่านการตรวจสอบ
ดังนั้นสิ่งที่มักจะเกิดขึ้นคือฉันคิดว่าโค้ดบางส่วนเช่นนี้ (นี่เป็นเพียงตัวอย่างเพื่อประโยชน์ของตัวอย่างไม่ต้องสนใจฟังก์ชั่นที่ใช้งานตัวอย่างใน 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();
}
ตกลงดังนั้นพูดได้ว่าevenSize
มาจากการป้อนข้อมูลของผู้ใช้ ดังนั้นฉันไม่แน่ใจว่ามันจะเป็นเช่นนั้น แต่ฉันไม่ต้องการเรียกวิธีนี้โดยมีความเป็นไปได้ที่จะมีข้อผิดพลาดเกิดขึ้น ดังนั้นฉันจึงทำฟังก์ชั่นต่อไปนี้:
public static boolean isEven(int evenSize) {
return evenSize % 2 == 0;
}
แต่ตอนนี้ฉันมีสองการตรวจสอบที่ดำเนินการตรวจสอบการป้อนข้อมูลเหมือนกัน: การแสดงออกในคำสั่งและการตรวจสอบอย่างชัดเจนในif
isEven
ทำซ้ำรหัสไม่ดีดังนั้นเราจะทำการ refactor:
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();
}
ตกลงนั่นแก้ไขได้ แต่ตอนนี้เราเข้าสู่สถานการณ์ต่อไปนี้:
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
ยังคงทำการตรวจสอบพารามิเตอร์ซึ่งจะคืนค่าจริงเสมอเมื่อเราเรียกฟังก์ชันนี้แล้ว
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();
}
แต่สิ่งนี้ต้องใช้ความคิดที่ชาญฉลาดและค่อนข้าง refactor ขนาดใหญ่
มีวิธีการทั่วไป (เพิ่มเติม) ที่เราสามารถหลีกเลี่ยงการโทรซ้ำซ้อนisEven
และดำเนินการตรวจสอบพารามิเตอร์ซ้ำได้หรือไม่? ฉันต้องการวิธีการแก้ปัญหาที่จะไม่โทรpadToEven
ด้วยพารามิเตอร์ที่ไม่ถูกต้องจริงเรียกข้อยกเว้น
ไม่มีข้อยกเว้นฉันไม่ได้หมายถึงการเขียนโปรแกรมที่ไม่มีข้อยกเว้นฉันหมายความว่าการป้อนข้อมูลของผู้ใช้ไม่ทำให้เกิดข้อยกเว้นจากการออกแบบในขณะที่ฟังก์ชั่นทั่วไปยังคงมีการตรวจสอบพารามิเตอร์ (ถ้าเพียงเพื่อป้องกันข้อผิดพลาดการเขียนโปรแกรม)
padToEvenWithIsEven
ว่าไม่ได้ทำการตรวจสอบความถูกต้องของการป้อนข้อมูลของผู้ใช้ มันทำการตรวจสอบความถูกต้องของอินพุตเพื่อป้องกันตัวเองจากข้อผิดพลาดในการเขียนโปรแกรมในรหัสการโทร การตรวจสอบความถูกต้องนี้ต้องขึ้นอยู่กับการวิเคราะห์ค่าใช้จ่าย / ความเสี่ยงซึ่งคุณต้องเสียค่าใช้จ่ายในการตรวจสอบกับความเสี่ยงที่บุคคลที่เขียนรหัสการโทรผ่านในพารามิเตอร์ที่ไม่ถูกต้อง