สิ่งนี้สำหรับฉันดูเหมือนว่าเป็นปัญหาที่พบได้ทั่วไปพอสมควรที่ผู้พัฒนาระดับต้นถึงระดับกลางมักเผชิญในบางประเด็น: พวกเขาไม่รู้หรือไม่เชื่อถือสัญญาที่พวกเขาเข้าร่วม นอกจากนี้เมื่อเขียนรหัสของตัวเองพวกเขามักจะพึ่งพาการคืนค่าโมฆะเพื่อระบุสิ่งที่ต้องการให้ผู้โทรตรวจสอบค่า Null
หากต้องการใช้อีกวิธีหนึ่งมีสองกรณีที่การตรวจสอบโมฆะเกิดขึ้น:
เมื่อ null เป็นคำตอบที่ถูกต้องในเงื่อนไขของสัญญา และ
ในกรณีที่มันไม่ตอบสนองที่ถูกต้อง
(2) เป็นเรื่องง่าย ใช้assert
ข้อความสั่ง (ยืนยัน) หรืออนุญาตความล้มเหลว (ตัวอย่างเช่น NullPointerException ) การยืนยันเป็นคุณลักษณะ Java ที่มีการใช้งานต่ำซึ่งถูกเพิ่มใน 1.4 ไวยากรณ์คือ:
assert <condition>
หรือ
assert <condition> : <object>
โดยที่<condition>
เป็นนิพจน์บูลีนและ<object>
เป็นวัตถุที่toString()
เอาต์พุตของเมธอดจะรวมอยู่ในข้อผิดพลาด
assert
คำสั่งพ่นError
( AssertionError
) ถ้าเงื่อนไขไม่เป็นความจริง โดยค่าเริ่มต้น Java ละเว้นการยืนยัน คุณสามารถเปิดใช้งานการยืนยันด้วยการส่งตัวเลือก-ea
ไปที่ JVM คุณสามารถเปิดใช้งานและปิดใช้งานการยืนยันสำหรับแต่ละคลาสและแพ็คเกจ ซึ่งหมายความว่าคุณสามารถตรวจสอบรหัสด้วยการยืนยันในขณะที่การพัฒนาและการทดสอบและปิดการใช้งานในสภาพแวดล้อมการผลิตแม้ว่าการทดสอบของฉันแสดงให้เห็นว่าไม่มีผลกระทบต่อประสิทธิภาพจากการยืนยัน
การไม่ใช้การยืนยันในกรณีนี้ก็โอเคเพราะรหัสเพิ่งจะล้มเหลวซึ่งเป็นสิ่งที่จะเกิดขึ้นหากคุณใช้การยืนยัน ความแตกต่างเพียงอย่างเดียวคือการยืนยันว่ามันอาจเกิดขึ้นเร็วกว่าในแบบที่มีความหมายมากกว่าและอาจมีข้อมูลเพิ่มเติมซึ่งอาจช่วยให้คุณเข้าใจว่าทำไมมันถึงเกิดขึ้นถ้าคุณไม่ได้คาดหวัง
(1) ยากขึ้นเล็กน้อย หากคุณไม่สามารถควบคุมรหัสที่คุณโทรได้แสดงว่าคุณติดขัดอยู่ หาก null เป็นคำตอบที่ถูกต้องคุณต้องตรวจสอบ
หากเป็นโค้ดที่คุณควบคุมได้ (และนี่ก็เป็นเรื่องปกติ) นั่นเป็นเรื่องอื่น หลีกเลี่ยงการใช้ค่า null เป็นคำตอบ ด้วยวิธีที่คืนค่าคอลเลคชันมันง่าย: คืนค่าคอลเลคชั่นที่ว่างเปล่า (หรืออาร์เรย์) แทนค่า Null ที่ค่อนข้างตลอดเวลา
ด้วยการไม่สะสมอาจเป็นเรื่องยาก ลองพิจารณาสิ่งนี้เป็นตัวอย่าง: หากคุณมีอินเตอร์เฟสเหล่านี้:
public interface Action {
void doSomething();
}
public interface Parser {
Action findAction(String userInput);
}
ที่ Parser รับอินพุตผู้ใช้แบบ raw และค้นหาสิ่งที่ต้องทำบางทีถ้าคุณกำลังใช้อินเตอร์เฟสบรรทัดคำสั่งสำหรับบางสิ่ง ตอนนี้คุณอาจทำสัญญาว่าจะส่งคืน null ถ้าไม่มีการกระทำที่เหมาะสม นั่นนำไปสู่การตรวจสอบโมฆะที่คุณกำลังพูดถึง
ทางเลือกอื่นคือไม่คืนค่า Null และใช้รูปแบบ Null Objectแทน:
public class MyParser implements Parser {
private static Action DO_NOTHING = new Action() {
public void doSomething() { /* do nothing */ }
};
public Action findAction(String userInput) {
// ...
if ( /* we can't find any actions */ ) {
return DO_NOTHING;
}
}
}
เปรียบเทียบ:
Parser parser = ParserFactory.getParser();
if (parser == null) {
// now what?
// this would be an example of where null isn't (or shouldn't be) a valid response
}
Action action = parser.findAction(someInput);
if (action == null) {
// do nothing
} else {
action.doSomething();
}
ถึง
ParserFactory.getParser().findAction(someInput).doSomething();
ซึ่งเป็นการออกแบบที่ดีกว่ามากเพราะนำไปสู่รหัสที่กระชับยิ่งขึ้น
ที่กล่าวว่าอาจเป็นวิธีที่เหมาะสมอย่างยิ่งสำหรับวิธี findAction () ในการโยนข้อยกเว้นด้วยข้อความแสดงข้อผิดพลาดที่มีความหมาย - โดยเฉพาะอย่างยิ่งในกรณีนี้ที่คุณต้องพึ่งพาการป้อนข้อมูลของผู้ใช้ มันจะดีกว่ามากสำหรับวิธี findAction ที่จะโยนข้อยกเว้นกว่าวิธีการโทรเพื่อระเบิดด้วย NullPointerException อย่างง่ายโดยไม่มีคำอธิบาย
try {
ParserFactory.getParser().findAction(someInput).doSomething();
} catch(ActionNotFoundException anfe) {
userConsole.err(anfe.getMessage());
}
หรือถ้าคุณคิดว่ากลไก try / catch น่าเกลียดเกินไปไม่ทำอะไรเลยการกระทำเริ่มต้นของคุณควรให้ข้อเสนอแนะกับผู้ใช้
public Action findAction(final String userInput) {
/* Code to return requested Action if found */
return new Action() {
public void doSomething() {
userConsole.err("Action not found: " + userInput);
}
}
}