มันโอเคที่จะใช้ข้อยกเว้นเป็นเครื่องมือในการ "จับ" ข้อผิดพลาดก่อนหรือไม่?


29

ฉันใช้ข้อยกเว้นเพื่อตรวจสอบปัญหาก่อน ตัวอย่างเช่น:

public int getAverageAge(Person p1, Person p2){
    if(p1 == null || p2 == null)
        throw new IllegalArgumentException("One or more of input persons is null").
    return (p1.getAge() + p2.getAge()) / 2;
}

โปรแกรมของฉันไม่ควรผ่านnullในฟังก์ชั่นนี้ ฉันไม่เคยตั้งใจที่จะ อย่างไรก็ตามในขณะที่เราทุกคนรู้ว่าสิ่งที่ไม่ได้ตั้งใจเกิดขึ้นในการเขียนโปรแกรม

การโยนข้อยกเว้นหากปัญหานี้เกิดขึ้นช่วยให้ฉันสามารถตรวจสอบและแก้ไขได้ก่อนที่จะทำให้เกิดปัญหามากขึ้นในที่อื่น ๆ ในโปรแกรม ข้อยกเว้นหยุดโปรแกรมและบอกฉันว่า "มีสิ่งไม่ดีเกิดขึ้นที่นี่แก้ไขได้" แทนที่จะเป็นการnullเคลื่อนไหวรอบ ๆ โปรแกรมทำให้เกิดปัญหาที่อื่น

ตอนนี้คุณพูดถูกในกรณีนี้มันอาจnullจะทำให้เกิดNullPointerExceptionในทันทีดังนั้นมันอาจไม่ใช่ตัวอย่างที่ดีที่สุด

แต่ให้พิจารณาวิธีการเช่นนี้ตัวอย่างเช่น:

public void registerPerson(Person person){
    persons.add(person);
    notifyRegisterObservers(person); // sends the person object to all kinds of objects.
}

ในกรณีนี้ a nullตามพารามิเตอร์จะถูกส่งไปรอบ ๆ โปรแกรมและอาจทำให้เกิดข้อผิดพลาดได้ในภายหลังซึ่งยากที่จะติดตามกลับไปที่จุดเริ่มต้น

เปลี่ยนฟังก์ชั่นดังนี้:

public void registerPerson(Person person){
    if(person == null) throw new IllegalArgumentException("Input person is null.");
    persons.add(person);
    notifyRegisterObservers(person); // sends the person object to all kinds of objects.
}

ทำให้ฉันเห็นปัญหามากก่อนที่จะทำให้เกิดข้อผิดพลาดแปลก ๆ ในที่อื่น ๆ

นอกจากนี้การnullอ้างอิงเป็นพารามิเตอร์เป็นเพียงตัวอย่างเท่านั้น อาจเป็นปัญหาหลายประเภทจากการขัดแย้งที่ไม่ถูกต้องกับสิ่งอื่น มันจะดีกว่าเสมอที่จะพบพวกเขา แต่เนิ่นๆ


ดังนั้นคำถามของฉันคือ: เป็นวิธีปฏิบัติที่ดีหรือไม่ การใช้ข้อยกเว้นเป็นเครื่องมือป้องกันปัญหาดีหรือไม่? นี่เป็นแอปพลิเคชันที่ถูกต้องตามกฎหมายของข้อยกเว้นหรือมีปัญหาหรือไม่


2
ผู้ลงคะแนนสามารถอธิบายสิ่งที่ผิดกับคำถามนี้ได้หรือไม่
Giorgio

2
"ผิดพลาดเร็วผิดพลาดบ่อย"
Bryan Chen

16
นั่นคือสิ่งที่ยกเว้นสำหรับ
raptortech97

โปรดทราบว่าสัญญาการเข้ารหัสช่วยให้คุณตรวจสอบข้อผิดพลาดดังกล่าวได้หลายแบบ โดยทั่วไปจะดีกว่าการทิ้งข้อยกเว้นขณะใช้งานจริง การสนับสนุนและประสิทธิผลของสัญญาการเข้ารหัสแตกต่างกันไปตามภาษา
Brian

3
เนื่องจากคุณกำลังขว้างปา IllegalArgumentException จึงเป็นการซ้ำซ้อนที่จะพูดว่า " บุคคลที่ป้อนข้อมูล "
kevin cline

คำตอบ:


29

ใช่ "ล้มเหลวเร็ว" เป็นหลักการที่ดีมากและนี่เป็นเพียงวิธีหนึ่งในการนำไปปฏิบัติ และในวิธีการที่จะต้องคืนค่าที่เฉพาะเจาะจงไม่มีอะไรมากที่คุณสามารถทำได้เพื่อที่จะล้มเหลวอย่างจงใจ - มันคือการโยนข้อยกเว้นหรือก่อให้เกิดการยืนยัน ข้อยกเว้นควรจะส่งสัญญาณเงื่อนไข 'พิเศษ' และการตรวจสอบข้อผิดพลาดการเขียนโปรแกรมแน่นอนเป็นพิเศษ


ล้มเหลวในช่วงต้นเป็นวิธีที่จะไปหากไม่มีวิธีการกู้คืนจากข้อผิดพลาดหรือเงื่อนไข ตัวอย่างเช่นหากคุณต้องการคัดลอกไฟล์และเส้นทางต้นทางหรือปลายทางว่างเปล่าคุณควรทิ้งข้อผิดพลาดทันที
Michael Shopsin

เป็นที่รู้จักกันว่า "ล้มเหลวอย่างรวดเร็ว"
keuleJ

8

ใช่การโยนข้อยกเว้นเป็นความคิดที่ดี โยนพวกเขาก่อนโยนพวกเขาบ่อย ๆ โยนพวกเขากระหาย

ฉันรู้ว่ามีการอภิปราย "ข้อยกเว้นเทียบกับการยืนยัน" ด้วยพฤติกรรมพิเศษบางประเภท (โดยเฉพาะอย่างยิ่งสิ่งที่คิดว่าสะท้อนถึงข้อผิดพลาดในการเขียนโปรแกรม) ที่จัดการโดยการยืนยันที่สามารถ "รวบรวม" สำหรับรันไทม์มากกว่า แต่ปริมาณของประสิทธิภาพที่ใช้ในการตรวจสอบความถูกต้องเพิ่มเติมเพียงเล็กน้อยนั้นน้อยมากบนฮาร์ดแวร์ที่ทันสมัยและค่าใช้จ่ายเพิ่มเติมใด ๆ ที่เกินดุลโดยมูลค่าของการมีผลลัพธ์ที่ถูกต้องและไม่ถูกขัดจังหวะ ฉันไม่เคยพบ codebase ของแอปพลิเคชั่นที่ฉันต้องการ (ลบออก) เช็คที่รันไทม์

ฉันอยากจะบอกว่าฉันไม่ต้องการให้มีการตรวจสอบและเงื่อนไขเพิ่มเติมอีกมากมายในรหัสที่เป็นตัวเลขจำนวนมาก ... แต่ที่จริงแล้วที่ข้อผิดพลาดเชิงตัวเลขจำนวนมากถูกสร้างขึ้นและหากไม่ได้อ่านตรงนั้นจะเผยแพร่ออกไปด้านนอก ส่งผลต่อผลลัพธ์ทั้งหมด ดังนั้นแม้จะมีการตรวจสอบมีมูลค่าการทำ อันที่จริงแล้วอัลกอริธึมเชิงตัวเลขที่ดีที่สุดและมีประสิทธิภาพที่สุดบางตัวนั้นมาจากการประเมินข้อผิดพลาด

ที่สุดท้ายที่จะตระหนักถึงรหัสพิเศษมากคือรหัสที่ไวต่อความหน่วงซึ่งเงื่อนไขพิเศษสามารถทำให้แผงขายน้ำ ดังนั้นในช่วงกลางของระบบปฏิบัติการ DBMS และมิดเดิลแวร์เคอร์เนลอื่น ๆ และการจัดการการสื่อสาร / โปรโตคอลระดับต่ำ แต่อีกครั้งสิ่งเหล่านี้คือข้อผิดพลาดของสถานที่บางแห่งที่น่าจะเป็นที่สังเกตได้มากที่สุดและเอฟเฟกต์ (ความปลอดภัยความถูกต้องและความสมบูรณ์ของข้อมูล) ของพวกเขาจะสร้างความเสียหายมากที่สุด

การปรับปรุงอย่างหนึ่งที่ฉันพบคือไม่เพียง แต่สร้างข้อยกเว้นระดับพื้นฐานเท่านั้น IllegalArgumentExceptionดี แต่มันมาจากที่ใดก็ได้ แทบทุกภาษาจะไม่สามารถเพิ่มข้อยกเว้นที่กำหนดเองได้ สำหรับโมดูลจัดการบุคคลของคุณให้พูดว่า:

public class PersonArgumentException extends IllegalArgumentException {
    public MyException(String message) {
        super(message);
    }
}

จากนั้นเมื่อมีคนเห็น PersonArgumentExceptionมันชัดเจนว่ามาจากไหน มีการปรับสมดุลเกี่ยวกับจำนวนข้อยกเว้นที่กำหนดเองที่คุณต้องการเพิ่มเนื่องจากคุณไม่ต้องการทวีคูณเอนทิตีโดยไม่จำเป็น (Occam's Razor) บ่อยครั้งที่ข้อยกเว้นที่กำหนดเองไม่กี่อย่างเพียงพอที่จะส่งสัญญาณ "โมดูลนี้ไม่ได้รับข้อมูลที่ถูกต้อง!" หรือ "โมดูลนี้ไม่สามารถทำสิ่งที่ควรจะทำ!" ในลักษณะที่เฉพาะเจาะจงและปรับแต่ง แต่ไม่แม่นยำเกินไปจนคุณต้องนำลำดับชั้นของข้อยกเว้นทั้งหมดกลับมาใช้ใหม่ ฉันมักจะมาที่ข้อยกเว้นที่กำหนดเองชุดเล็กโดยเริ่มต้นด้วยข้อยกเว้นหุ้นแล้วสแกนรหัสและตระหนักว่า "สถานที่ N เหล่านี้กำลังเพิ่มข้อยกเว้นสต็อก แต่พวกเขาต้มลงไปสู่แนวคิดระดับสูงกว่า พวกเขาต้องการ; '


I've never actually met an application codebase for which I'd want (most) checks removed at runtime. จากนั้นคุณยังไม่ได้ทำโค้ดที่สำคัญต่อประสิทธิภาพ ฉันกำลังทำงานกับบางสิ่งบางอย่างในขณะนี้ที่ทำ 37M ops ต่อวินาทีด้วยคำยืนยันที่รวบรวมในและ 42M โดยไม่มีพวกเขา การยืนยันไม่ได้มีการตรวจสอบอินพุตภายนอกพวกเขาอยู่ที่นั่นเพื่อให้แน่ใจว่ารหัสถูกต้อง ลูกค้าของฉันมีความสุขมากกว่าที่จะเพิ่มขึ้น 13% เมื่อฉันพอใจว่าสิ่งของของฉันไม่แตก
Blrfl

ควรหลีกเลี่ยงการใช้ codebase พร้อมกับข้อยกเว้นที่กำหนดเองเพราะมันอาจช่วยคุณได้ แต่ก็ไม่ได้ช่วยคนอื่นที่ต้องทำความคุ้นเคยกับพวกเขา โดยปกติถ้าคุณพบว่าตัวเองมีข้อยกเว้นเพิ่มเติมและไม่ได้เพิ่มสมาชิกหรือฟังก์ชันใด ๆ คุณไม่จำเป็นต้องใช้มัน แม้จะอยู่ในตัวอย่างของคุณจะไม่เป็นที่ชัดเจนเป็นPersonArgumentException IllegalArgumentExceptionหลังเป็นที่รู้จักกันทั่วโลกที่จะโยนเมื่อมีการโต้แย้งที่ผิดกฎหมายจะถูกส่งผ่าน ฉันคาดหวังว่าอดีตจะถูกโยนถ้า a Personอยู่ในสถานะที่ไม่ถูกต้องสำหรับการโทร (คล้ายกับInvalidOperationExceptionใน C #)
Selali Adobor

เป็นเรื่องจริงที่ว่าหากคุณไม่ระวังคุณสามารถเรียกใช้ข้อยกเว้นเดียวกันจากที่อื่นในฟังก์ชันได้ แต่นั่นเป็นข้อบกพร่องของรหัสไม่ใช่ลักษณะของข้อยกเว้นทั่วไป และนั่นคือจุดที่การดีบักและการติดตามสแต็กเข้ามาหากคุณพยายามที่จะ "ติดป้าย" ข้อยกเว้นของคุณให้ใช้สิ่งอำนวยความสะดวกที่มีอยู่ซึ่งข้อยกเว้นทั่วไปส่วนใหญ่มีให้เช่นใช้ตัวสร้างข้อความ ข้อยกเว้นบางอย่างให้พารามิเตอร์ที่สร้างเพิ่มเติมเพื่อรับชื่อของอาร์กิวเมนต์ที่มีปัญหา แต่คุณสามารถให้สิ่งอำนวยความสะดวกเดียวกันกับข้อความที่มีรูปแบบที่ดี
Selali Adobor

ฉันยอมรับว่าเพียง rebranding ข้อยกเว้นทั่วไปให้กับป้ายชื่อส่วนตัวโดยทั่วไปข้อยกเว้นเดียวกันเป็นตัวอย่างที่อ่อนแอและไม่ค่อยคุ้มค่าความพยายาม ในทางปฏิบัติฉันพยายามที่จะปล่อยข้อยกเว้นที่กำหนดเองในระดับความหมายที่สูงกว่าผูกติดอยู่กับเจตนาของโมดูล
Jonathan Eunice

ฉันได้ทำงานที่ไวต่อประสิทธิภาพในขอบเขตตัวเลข / HPC และ OS / มิดเดิลแวร์ การชนที่มีประสิทธิภาพ 13% นั้นไม่ใช่เรื่องเล็ก ฉันอาจปิดการตรวจสอบบางอย่างเพื่อให้ได้เช่นเดียวกับผู้บัญชาการทหารอาจขอ 105% ของเอาท์พุทเครื่องปฏิกรณ์น้อย แต่ฉันเคยเห็นว่า "มันจะทำงานได้เร็วขึ้นด้วยวิธีนี้" ที่ให้ไว้บ่อยครั้งเพื่อปิดการตรวจสอบการสำรองข้อมูลและการป้องกันอื่น ๆ โดยทั่วไปแล้วเป็นการแลกเปลี่ยนความยืดหยุ่นและความปลอดภัย (ในหลายกรณีรวมถึงความถูกต้องของข้อมูล) เพื่อประสิทธิภาพที่เพิ่มขึ้น ไม่ว่าจะคุ้มค่าคือการตัดสิน
Jonathan Eunice

3

การล้มเหลวโดยเร็วที่สุดจะดีมากเมื่อทำการดีบั๊กแอปพลิเคชัน ฉันจำข้อผิดพลาดการแบ่งส่วนเฉพาะในโปรแกรม C ++ แบบดั้งเดิม: สถานที่ที่ตรวจพบข้อผิดพลาดไม่มีส่วนเกี่ยวข้องกับสถานที่ที่ถูกนำมาใช้ (ตัวชี้โมฆะถูกย้ายอย่างมีความสุขจากที่หนึ่งไปยังอีกที่หนึ่งในหน่วยความจำ ) การติดตามสแต็กไม่สามารถช่วยคุณได้ในกรณีเหล่านี้

ใช่แล้วการตั้งโปรแกรมป้องกันเป็นวิธีที่มีประสิทธิภาพจริงๆในการตรวจจับและแก้ไขข้อบกพร่องได้อย่างรวดเร็ว ในทางกลับกันมันอาจมากเกินไปโดยเฉพาะอย่างยิ่งกับการอ้างอิงที่เป็นโมฆะ

ในกรณีเฉพาะของคุณตัวอย่างเช่น: หากการอ้างอิงใด ๆ ที่เป็นโมฆะNullReferenceExceptionจะถูกโยนไปที่คำสั่งถัดไปเมื่อพยายามที่จะอายุของคนคนหนึ่ง คุณไม่จำเป็นจริงๆที่จะตรวจสอบสิ่งที่ได้ด้วยตัวเองที่นี่: ให้ระบบจับพื้นฐานข้อผิดพลาดเหล่านั้นและโยนข้อยกเว้นที่ว่าทำไมพวกเขามีอยู่

สำหรับตัวอย่างที่สมจริงยิ่งขึ้นคุณสามารถใช้assertข้อความสั่งซึ่ง:

  1. สั้นกว่าในการเขียนและอ่าน:

        assert p1 : "p1 is null";
        assert p2 : "p2 is null";
    
  2. ได้รับการออกแบบมาโดยเฉพาะสำหรับวิธีการของคุณ ในโลกที่คุณมีทั้งคำยืนยันและข้อยกเว้นคุณสามารถแยกแยะได้ดังนี้:

    • การยืนยันเป็นข้อผิดพลาดในการเขียนโปรแกรม ("/ * สิ่งนี้ไม่ควรเกิดขึ้น * /")
    • ข้อยกเว้นสำหรับกรณีมุม (สถานการณ์พิเศษ แต่น่าจะเป็น)

ดังนั้นการเปิดเผยสมมติฐานของคุณเกี่ยวกับอินพุตและ / หรือสถานะของแอปพลิเคชันของคุณด้วยการยืนยันให้นักพัฒนาซอฟต์แวร์รายต่อไปเข้าใจวัตถุประสงค์ของรหัสของคุณอีกเล็กน้อย

ตัววิเคราะห์แบบสแตติก (เช่นคอมไพเลอร์) อาจมีความสุขเช่นกัน

ในที่สุดสามารถลบคำยืนยันออกจากแอ็พพลิเคชันที่ปรับใช้โดยใช้สวิตช์เดียว แต่โดยทั่วไปแล้วอย่าคาดหวังว่าจะปรับปรุงประสิทธิภาพด้วย: การตรวจสอบยืนยันที่รันไทม์นั้นไม่มีความสำคัญ


1

เท่าที่ฉันรู้โปรแกรมเมอร์ที่แตกต่างต้องการทางออกหนึ่งหรืออื่น ๆ

มักจะต้องการวิธีแก้ปัญหาแรกเนื่องจากมีความรัดกุมมากกว่าโดยเฉพาะคุณไม่ต้องตรวจสอบสภาพเดิมซ้ำแล้วซ้ำอีกในฟังก์ชั่นต่าง ๆ

ฉันพบทางออกที่สองเช่น

public void registerPerson(Person person){
    if(person == null) throw new IllegalArgumentException("Input person is null.");
    persons.add(person);
    notifyRegisterObservers(person); // sends the person object to all kinds of objects.
}

แข็งกว่าเพราะ

  1. มันจะจับข้อผิดพลาดโดยเร็วที่สุดเช่นเมื่อregisterPerson()ถูกเรียกไม่ใช่เมื่อข้อยกเว้นตัวชี้โมฆะถูกโยนลงที่ใดที่หนึ่งในสแต็คการโทร การดีบักง่ายขึ้นมาก: เราทุกคนรู้ว่าค่าที่ไม่ถูกต้องสามารถเดินทางผ่านโค้ดได้นานแค่ไหนก่อนที่มันจะปรากฏตัวเป็นบั๊ก
  2. มันลดการคัปปลิ้งระหว่างฟังก์ชั่น: registerPerson()ไม่ได้ทำการตั้งสมมติฐานใด ๆ ว่าฟังก์ชั่นอื่น ๆ จะลงเอยด้วยการใช้personข้อโต้แย้งอย่างไรและจะใช้งานอย่างไร: การตัดสินใจที่nullเกิดข้อผิดพลาดจะถูกนำไปใช้

ดังนั้นโดยเฉพาะถ้ารหัสค่อนข้างซับซ้อนฉันมักจะชอบวิธีที่สองนี้


1
การให้เหตุผล ("บุคคลที่ป้อนเป็นโมฆะ") ยังช่วยให้เข้าใจปัญหาเช่นเดียวกับวิธีการปิดบังบางอย่างในไลบรารีที่ล้มเหลว
Florian F

1

โดยทั่วไปใช่มันเป็นความคิดที่ดีที่จะ "ล้มเหลวเร็ว" อย่างไรก็ตามในตัวอย่างที่เฉพาะเจาะจงของคุณชัดเจนIllegalArgumentExceptionไม่ได้ให้การปรับปรุงที่สำคัญกว่าNullReferenceException- เพราะวัตถุทั้งสองดำเนินการเมื่อถูกส่งเป็นข้อโต้แย้งไปยังฟังก์ชั่นแล้ว

แต่ลองดูตัวอย่างที่แตกต่างกันเล็กน้อย

class PersonCalculator {
    PersonCalculator(Person p) {
        if (p == null) throw new ArgumentNullException("p");
        _p = p;
    }

    void Calculate() {
        // Do something to p
    }
}

หากมีข้อโต้แย้งในการตรวจสอบการสร้างไม่มีคุณจะได้รับเมื่อโทรNullReferenceExceptionCalculate

แต่โค้ดที่ใช้งานไม่ได้นั้นไม่ใช่ทั้งCalculateฟังก์ชั่นและผู้บริโภคของCalculateฟังก์ชั่น ชิ้นส่วนของรหัสที่เสียหายคือรหัสที่พยายามสร้างPersonCalculatorด้วยค่า Null Personดังนั้นเราจึงต้องการให้ข้อยกเว้นเกิดขึ้น

หากเราลบการตรวจสอบการโต้แย้งที่ชัดเจนคุณจะต้องทราบสาเหตุที่NullReferenceExceptionเกิดขึ้นเมื่อมีการCalculateเรียก และติดตามว่าทำไมวัตถุจึงถูกสร้างขึ้นมาพร้อมกับnullคน ๆ นั้นจะมีเล่ห์เหลี่ยมโดยเฉพาะอย่างยิ่งหากโค้ดที่สร้างเครื่องคิดเลขไม่ใกล้กับรหัสที่เรียกCalculateฟังก์ชันจริง ๆ


0

ไม่ได้อยู่ในตัวอย่างที่คุณให้

อย่างที่คุณพูดการขว้างปาอย่างชัดเจนไม่ได้ดึงดูดคุณมากนักเมื่อคุณได้รับการยกเว้นหลังจากนั้นไม่นาน หลายคนยืนยันว่าการมีข้อยกเว้นที่ชัดเจนพร้อมข้อความที่ดีนั้นดีกว่าแม้ว่าฉันจะไม่เห็นด้วยก็ตาม ในสถานการณ์ก่อนวางจำหน่ายการติดตามสแต็กจะดีพอ ในสถานการณ์หลังวางจำหน่ายไซต์การโทรมักจะให้ข้อความที่ดีกว่าภายในฟังก์ชัน

รูปแบบที่สองคือการให้ข้อมูลกับฟังก์ชั่นมากเกินไป ฟังก์ชั่นนั้นไม่จำเป็นต้องรู้ว่าฟังก์ชั่นอื่น ๆ จะส่งสัญญาณอินพุตเป็นโมฆะ แม้ว่าพวกเขาจะใส่อินพุตว่างในตอนนี้มันก็กลายเป็นปัญหามากที่ refactor ควรที่จะหยุดเป็นกรณีตั้งแต่การตรวจสอบโมฆะจะกระจายไปทั่วรหัส

แต่โดยทั่วไปคุณควรโยนเร็ว ๆ เมื่อคุณพบว่ามีบางอย่างผิดปกติ (ในขณะที่เคารพ DRY) แม้ว่าสิ่งเหล่านี้อาจไม่ใช่ตัวอย่างที่ดีของสิ่งนั้น


-3

ในฟังก์ชั่นตัวอย่างของคุณฉันต้องการให้คุณไม่ทำการตรวจสอบและอนุญาตให้NullReferenceExceptionเกิดขึ้น

สำหรับหนึ่งก็ทำให้รู้สึกไม่ว่าจะเป็นผ่าน null NullReferenceExceptionมีอยู่แล้วดังนั้นฉันจะคิดออกปัญหาทันทีอยู่บนพื้นฐานของการขว้างปาของที่

สองคือถ้าทุกฟังก์ชั่นการโยนข้อยกเว้นแตกต่างกันเล็กน้อยตามชนิดของการป้อนข้อมูลผิดที่เห็นได้ชัดแล้วในไม่ช้าคุณก็มีฟังก์ชั่นที่อาจส่งข้อยกเว้นต่าง ๆ 18 ชนิดและในไม่ช้าคุณก็พบว่า ทำงานมากที่จะจัดการกับและเพียงแค่กำจัดข้อยกเว้นทั้งหมดอยู่ดี

ไม่มีสิ่งใดที่คุณสามารถทำได้เพื่อช่วยให้สถานการณ์ข้อผิดพลาดขณะออกแบบในฟังก์ชั่นของคุณดังนั้นเพียงแค่ปล่อยให้ความล้มเหลวเกิดขึ้นโดยไม่ต้องเปลี่ยนมัน


ฉันทำงานเป็นเวลาสองสามปีบนพื้นฐานของรหัสที่ยึดตามหลักการนี้: พอยน์เตอร์จะถูกยกเลิกการอ้างอิงเมื่อจำเป็นและแทบไม่เคยตรวจสอบกับ NULL และจัดการอย่างชัดเจน การดีบักรหัสนี้ใช้เวลานานและลำบากเนื่องจากข้อยกเว้น (หรือการถ่ายโอนข้อมูลหลัก) เกิดขึ้นมากในภายหลัง wrt จุดที่ข้อผิดพลาดเชิงตรรกะคือ ฉันเสียเวลาไปหลายสัปดาห์เพื่อหาข้อบกพร่องบางอย่าง ด้วยเหตุผลเหล่านี้ฉันชอบสไตล์ที่ล้มเหลวเร็วที่สุดเท่าที่เป็นไปได้อย่างน้อยสำหรับโค้ดที่ซับซ้อนซึ่งไม่ชัดเจนในทันทีที่มีข้อยกเว้นตัวชี้โมฆะมาจาก
Giorgio

"สำหรับอันหนึ่งมันไม่มีเหตุผลที่จะผ่านโมฆะไปเลยดังนั้นฉันจะหาปัญหาได้ทันทีจากการขว้าง NullReferenceException": ไม่จำเป็นต้องเป็นตัวอย่างที่สองของ Prog
Giorgio

"สองคือถ้าทุกฟังก์ชันโยนข้อยกเว้นที่แตกต่างกันเล็กน้อยตามชนิดของอินพุตที่ผิดที่เห็นได้ชัดแล้วในไม่ช้าคุณก็มีฟังก์ชั่นที่อาจส่งข้อยกเว้นต่าง ๆ 18 ชนิด ... ": ในกรณีนี้คุณ สามารถใช้ข้อยกเว้นเดียวกัน (แม้ NullPointerException) ในทุกฟังก์ชั่น: สิ่งที่สำคัญคือการโยนเร็วไม่ให้ยกเว้นข้อแตกต่างจากแต่ละฟังก์ชั่น
Giorgio

นั่นคือสิ่งที่ RuntimeExceptions ใช้ เงื่อนไขใด ๆ ที่ "ไม่ควรเกิดขึ้น" แต่จะป้องกันไม่ให้โค้ดของคุณทำงานได้ คุณไม่จำเป็นต้องประกาศในลายเซ็นวิธีการ แต่คุณต้องจับพวกมันในบางจุดและรายงานว่าฟังก์ชันที่การร้องขอ requestd นั้นล้มเหลว
Florian F

1
คำถามไม่ได้ระบุภาษาดังนั้นการพึ่งพาเช่นRuntimeExceptionไม่จำเป็นต้องใช้สมมติฐานที่ถูกต้อง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.