ข้อยกเว้น 'จำนวนดี' ที่จะนำไปใช้กับห้องสมุดของฉันคืออะไร


20

ฉันสงสัยอยู่เสมอว่ามีกี่คลาสข้อยกเว้นที่แตกต่างกันที่ฉันควรนำไปใช้กับซอฟต์แวร์ของฉัน การพัฒนาเฉพาะของฉันมักจะเกี่ยวข้องกับ C ++ / C # / Java แต่ฉันเชื่อว่านี่เป็นคำถามสำหรับทุกภาษา

ฉันต้องการที่จะเข้าใจว่าอะไรคือข้อยกเว้นที่แตกต่างกันจำนวนมากและชุมชนนักพัฒนาคาดหวังอะไรกับห้องสมุดที่ดี

การแลกเปลี่ยนที่ฉันเห็นรวมถึง:

  • คลาสยกเว้นเพิ่มเติมสามารถอนุญาตให้มีการจัดการข้อผิดพลาดในระดับดีมากสำหรับผู้ใช้ API (มีแนวโน้มที่จะกำหนดค่าผู้ใช้หรือข้อผิดพลาดข้อมูลหรือไม่พบไฟล์)
  • คลาสข้อยกเว้นเพิ่มเติมอนุญาตให้ข้อมูลเฉพาะข้อผิดพลาดถูกฝังอยู่ในข้อยกเว้นไม่ใช่เพียงแค่ข้อความสตริงหรือรหัสข้อผิดพลาด
  • คลาสยกเว้นเพิ่มเติมอาจหมายถึงการบำรุงรักษาโค้ดเพิ่มเติม
  • คลาสที่มีข้อยกเว้นเพิ่มเติมอาจหมายความว่า API นั้นเข้าถึงผู้ใช้ได้น้อยกว่า

สถานการณ์ที่ฉันต้องการเข้าใจการใช้งานข้อยกเว้นรวมถึง:

  • ในช่วง 'การกำหนดค่า' ซึ่งอาจรวมถึงการโหลดไฟล์หรือการตั้งค่าพารามิเตอร์
  • ระหว่างเฟส 'การดำเนินการ' ที่ไลบรารีอาจกำลังทำงานและทำงานบางอย่างอาจอยู่ในเธรดอื่น

รูปแบบอื่น ๆ ของการรายงานข้อผิดพลาดโดยไม่ใช้ข้อยกเว้นหรือข้อยกเว้นน้อยกว่า (เป็นการเปรียบเทียบ) อาจรวมถึง:

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

ในฐานะนักพัฒนาคุณต้องการเห็นอะไร

หากมีข้อยกเว้นหลายประการคุณสนใจที่จะจัดการข้อผิดพลาดแยกต่างหากหรือไม่?

คุณมีการตั้งค่าสำหรับประเภทการจัดการข้อผิดพลาดขึ้นอยู่กับขั้นตอนการทำงานหรือไม่?


1
อาจเกี่ยวข้อง: programmers.stackexchange.com/questions/3713/…
Fuzz

5
"API นั้นเข้าถึงผู้ใช้น้อยกว่า" - สามารถจัดการได้โดยมีคลาสยกเว้นหลายคลาสซึ่งสืบทอดมาจากคลาสพื้นฐานทั่วไปสำหรับ API จากนั้นเมื่อคุณเริ่มต้นใช้งานคุณสามารถดูว่าข้อยกเว้น API ใดมาจากโดยไม่ต้องกังวลเกี่ยวกับรายละเอียดทั้งหมด เมื่อถึงเวลาที่คุณทำโปรแกรมแรกของคุณโดยใช้ API แล้วหากคุณต้องการข้อมูลเพิ่มเติมเกี่ยวกับข้อผิดพลาดคุณจะเริ่มต้นดูว่าข้อยกเว้นที่แตกต่างกันจริงๆหมายถึงอะไร แน่นอนว่าคุณต้องเล่นอย่างดีพร้อมกับลำดับชั้นข้อยกเว้นมาตรฐานของภาษาที่คุณใช้
Steve Jessop

ประเด็นที่เกี่ยวข้องกับสตีฟ
Fuzz

คำตอบ:


18

ฉันทำให้มันง่าย

ไลบรารีมีชนิดข้อยกเว้นพื้นฐานที่เพิ่มเติมจาก std ::: runtime_error (ซึ่งมาจากภาษา C ++ มีความเหมาะสมกับภาษาอื่น ๆ ) ข้อยกเว้นนี้ใช้สตริงข้อความเพื่อให้เราสามารถเข้าสู่ระบบ; จุดส่งสัญญาณทุกจุดจะมีข้อความที่ไม่ซ้ำกัน

เกี่ยวกับมัน.

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

หมายเหตุ 2 : บางครั้งไลบรารีนั้นง่ายมากมันไม่คุ้มที่จะให้มันเป็นข้อยกเว้นของตัวเองและ std :: runtime_error จะทำ สิ่งสำคัญคือต้องมีข้อยกเว้นถ้าความสามารถในการแยกความแตกต่างจาก std :: runtime_error สามารถให้ข้อมูลผู้ใช้เพียงพอที่จะทำอะไรกับมัน

หมายเหตุ 3 : ภายในชั้นเรียนฉันมักจะต้องการรหัสข้อผิดพลาด (แต่สิ่งเหล่านี้จะไม่หลบหนีข้าม API สาธารณะของชั้นเรียนของฉัน)

ดูการแลกเปลี่ยนของคุณ:

การแลกเปลี่ยนที่ฉันเห็นรวมถึง:

คลาสยกเว้นเพิ่มเติมสามารถอนุญาตให้มีการจัดการข้อผิดพลาดในระดับดีมากสำหรับผู้ใช้ API (มีแนวโน้มที่จะกำหนดค่าผู้ใช้หรือข้อผิดพลาดข้อมูลหรือไม่พบไฟล์)

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

คลาสข้อยกเว้นเพิ่มเติมอนุญาตให้ข้อมูลเฉพาะข้อผิดพลาดถูกฝังอยู่ในข้อยกเว้นไม่ใช่เพียงแค่ข้อความสตริงหรือรหัสข้อผิดพลาด

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

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

ข้อยกเว้นน้อยกว่า แต่ฝังรหัสข้อผิดพลาดที่สามารถใช้เป็นการค้นหา

คุณต้องตรวจสอบสภาพอากาศว่าสามารถใช้รหัสข้อผิดพลาดได้อย่างมีความหมาย หากทำได้คุณควรมีข้อยกเว้นของตนเอง มิฉะนั้นผู้ใช้ของคุณต้องใช้คำสั่ง switch ภายใน catch (ซึ่งเอาชนะจุดทั้งหมดของการจับโดยอัตโนมัติ)

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

การส่งคืนรหัสข้อผิดพลาดและการตั้งค่าสถานะโดยตรงจากฟังก์ชั่น (บางครั้งไม่สามารถทำได้จากกระทู้)

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

ใช้งานเหตุการณ์หรือระบบติดต่อกลับเมื่อเกิดข้อผิดพลาด (หลีกเลี่ยงการคลายสแต็ก)

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

แต่ถ้าคุณไม่สามารถดำเนินการต่อในข้อยกเว้นสแต็กจะคลาย (สำหรับเธรดอย่างน้อย)


+1; ถึงแม้ว่าตอนนี้ผู้ใช้ของคุณจะต้องใช้คำสั่งสวิตช์ภายใน catch (ซึ่งเอาชนะจุดทั้งหมดของการจับโดยอัตโนมัติ) - คลี่คลายสแตกการโทร (หากคุณยังสามารถใช้งานได้) และการจัดการข้อผิดพลาดที่บังคับยังคงเป็นประโยชน์ที่ดี แต่แน่นอนว่ามันจะเบี่ยงเบนไปจากความสามารถในการโทรสแต็กคลี่คลายเมื่อคุณต้องจับมันไว้ตรงกลางและหมุนใหม่
Merlyn Morgan-Graham

9

ฉันมักจะเริ่มต้นด้วย:

  1. ชั้นยกเว้นสำหรับข้อบกพร่องข้อโต้แย้ง เช่น "การโต้เถียงไม่ได้รับอนุญาตให้เป็นโมฆะ", "การโต้แย้งต้องเป็นค่าบวก" และอื่น ๆ Java และ C # มีคลาสที่กำหนดไว้ล่วงหน้าสำหรับคลาสเหล่านั้น ใน C ++ ฉันมักจะสร้างเพียงหนึ่งคลาสที่ได้รับมาจาก std :: ข้อยกเว้น
  2. ชั้นยกเว้นสำหรับข้อบกพร่องที่จำเป็น สิ่งเหล่านี้ใช้สำหรับการทดสอบที่ซับซ้อนมากขึ้นเช่น "ดัชนีต้องมีขนาดเล็กกว่าขนาด"
  3. ชั้นยกเว้นสำหรับข้อบกพร่องยืนยัน สิ่งเหล่านี้ใช้สำหรับตรวจสอบสถานะของวิธีการลงครึ่งทาง เช่นเมื่อวนซ้ำรายการเพื่อนับองค์ประกอบที่เป็นลบศูนย์หรือบวกในตอนท้ายทั้งสามควรเพิ่มขนาด
  4. หนึ่งคลาสยกเว้นฐานสำหรับไลบรารีเอง ตอนแรกแค่โยนคลาสนี้ เฉพาะเมื่อมีความจำเป็นเกิดขึ้นให้เริ่มเพิ่มคลาสย่อย
  5. ฉันไม่ต้องการห่อยกเว้น แต่ฉันรู้ว่าความคิดเห็นแตกต่างกันในจุดนี้ (และมีความสัมพันธ์กับภาษาที่ใช้) ถ้าคุณทำห่อคุณจะต้องเพิ่มเติมการเรียนการตัดข้อยกเว้น

เนื่องจากคลาสสำหรับ 3 เคสแรกนั้นมีการดีบักเอดส์พวกมันไม่ได้ตั้งใจที่จะจัดการด้วยรหัส แต่ควรจับผู้จัดการระดับบนสุดเท่านั้นที่แสดงข้อมูลดังกล่าวซึ่งผู้ใช้สามารถคัดลอกวางไปยังนักพัฒนาซอฟต์แวร์ (หรือดีกว่า: กดปุ่ม "ส่งรายงาน") ดังนั้นรวมถึงข้อมูลที่เป็นประโยชน์สำหรับนักพัฒนา: ไฟล์ฟังก์ชั่นหมายเลขบรรทัดและข้อความบางอย่างที่ระบุอย่างชัดเจนว่าการตรวจสอบล้มเหลว

เนื่องจาก 3 กรณีแรกนั้นเหมือนกันสำหรับแต่ละโครงการใน C ++ ฉันมักจะคัดลอกจากโครงการก่อนหน้า เนื่องจากหลายคนทำสิ่งเดียวกันผู้ออกแบบของ C # และ Java ได้เพิ่มคลาสมาตรฐานสำหรับเคสเหล่านั้นในไลบรารีมาตรฐาน [อัพเดต:]สำหรับโปรแกรมเมอร์ที่ขี้เกียจ: หนึ่งคลาสอาจเพียงพอและโชคดีที่ห้องสมุดมาตรฐานของคุณมีคลาสยกเว้นที่เหมาะสมอยู่แล้ว ฉันต้องการเพิ่มข้อมูลเช่นชื่อไฟล์และชุดเครื่องนอนซึ่งคลาสเริ่มต้นใน C ++ ไม่มีให้ [อัพเดตล่าสุด]

กรณีที่สี่อาจมีเพียงหนึ่งคลาสเท่านั้นหรือขึ้นอยู่กับไลบรารี ฉันชอบ aproach แบบเปรียวเพื่อเริ่มต้นง่ายเพิ่มคลาสย่อยเมื่อจำเป็นต้องใช้

สำหรับการอภิปรายรายละเอียดเกี่ยวกับกรณีที่สี่ของฉันให้ดูคำตอบของโลกิ Astari ฉันเห็นด้วยอย่างยิ่งกับคำตอบโดยละเอียดของเขา


+1; มีความแตกต่างที่ชัดเจนระหว่างวิธีที่คุณควรเขียนข้อยกเว้นการเขียนในกรอบข้อว่าคุณควรเขียนข้อยกเว้นในแอปพลิเคชันอย่างไร ความแตกต่างนั้นค่อนข้างคลุมเครือ แต่คุณพูดถึงมัน (การละทิ้ง Loki สำหรับกรณีห้องสมุด)
Merlyn Morgan-Graham
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.