ข้อตกลงสำหรับข้อยกเว้นหรือรหัสข้อผิดพลาด


118

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

คุณใช้กฎอะไรในการตัดสินใจว่าคุณส่งข้อยกเว้นหรือส่งคืนรหัสข้อผิดพลาดสำหรับการรายงานข้อผิดพลาด

คำตอบ:


81

ในสิ่งระดับสูงข้อยกเว้น; ในสิ่งระดับต่ำรหัสข้อผิดพลาด

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

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

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


5
+1 เพื่อชี้ให้เห็นว่าบริบทมีส่วนเกี่ยวข้องกับกลยุทธ์การจัดการข้อผิดพลาด
alx9r

2
@ ทอมจุดดี แต่มีข้อยกเว้นรับรองโดนจับ เราจะแน่ใจได้อย่างไรว่ามีการตรวจจับรหัสข้อผิดพลาดและไม่ถูกเพิกเฉยเนื่องจากข้อผิดพลาด
Pacerier

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

3
C ++ 17 แนะนำnodiscardแอ็ตทริบิวต์ที่จะเตือนคอมไพเลอร์หากไม่ได้เก็บค่าส่งคืนของฟังก์ชัน ช่วยเล็กน้อยในการตรวจจับการตรวจสอบรหัสข้อผิดพลาดที่ลืม ตัวอย่าง: godbolt.org/g/6i6E0B
Zitrax

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

62

โดยปกติฉันชอบข้อยกเว้นเนื่องจากมีข้อมูลเชิงบริบทมากกว่าและสามารถถ่ายทอด (เมื่อใช้อย่างถูกต้อง) ข้อผิดพลาดไปยังโปรแกรมเมอร์ได้อย่างชัดเจน

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

เพื่อสรุปฉันชอบข้อยกเว้นมากกว่ารหัสข้อผิดพลาดในเกือบทุกสถานการณ์


4
"รหัสข้อผิดพลาดมีน้ำหนักเบากว่าข้อยกเว้น" ขึ้นอยู่กับสิ่งที่คุณวัดและวิธีการวัด มันค่อนข้างง่ายที่จะสร้างการทดสอบที่แสดงว่า API ที่ใช้ข้อยกเว้นนั้นเร็วกว่ามาก
Mooing Duck

1
@smink จุดดี แต่เราจะจัดการกับค่าใช้จ่ายของข้อยกเว้นได้อย่างไร? รหัสข้อผิดพลาดไม่เพียง แต่มีน้ำหนักเบาพวกเขามีพื้นน้ำหนัก ; ข้อยกเว้นไม่ใช่แค่น้ำหนักปานกลาง แต่เป็นวัตถุที่มีน้ำหนักมากซึ่งมีข้อมูลสแต็กและของอื่น ๆ ที่เราไม่ได้ใช้อยู่แล้ว
Pacerier

3
@Pacerier: คุณกำลังพิจารณาการทดสอบที่มีข้อยกเว้นเท่านั้น คุณคิดถูก 100% ที่ส่งข้อยกเว้น C ++ ช้ากว่าการส่งคืนรหัสข้อผิดพลาดอย่างมาก ลงมือไม่มีการอภิปราย ในกรณีที่เราไม่แตกต่างกันคืออีก 99.999% ของรหัส ด้วยข้อยกเว้นเราไม่จำเป็นต้องตรวจสอบการส่งคืนรหัสข้อผิดพลาดระหว่างแต่ละคำสั่งทำให้โค้ดนั้นเร็วขึ้น 1-50% (หรือไม่ขึ้นอยู่กับคอมไพเลอร์ของคุณ) ซึ่งหมายความว่าโค้ดแบบเต็มจะเร็วขึ้นหรือช้าลงขึ้นอยู่กับวิธีการเขียนโค้ดและความถี่ในการโยนข้อยกเว้น
Mooing Duck

1
@Pacerier: ด้วยการทดสอบเทียมที่ฉันเพิ่งเขียนขึ้นรหัสตามข้อยกเว้นนั้นเร็วพอ ๆ กับรหัสข้อผิดพลาดใน MSVC และเสียงดังแม้ว่าจะไม่ใช่ GCC: coliru.stacked-crooked.com/a/e81694e5c508945b (การกำหนดเวลาที่ด้านล่าง) ดูเหมือนว่าแฟล็ก GCC ที่ฉันใช้สร้างข้อยกเว้นที่ช้าผิดปกติเมื่อเทียบกับคอมไพเลอร์อื่น ๆ ฉันมีความลำเอียงดังนั้นโปรดวิจารณ์การทดสอบของฉันและลองใช้ตัวแปรอื่น
หมูปิ้ง

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

24

ฉันชอบข้อยกเว้นเพราะ

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

2
จุดที่สี่ของคุณไม่ยุติธรรม: สถานะข้อผิดพลาดเมื่อแปลงเป็นวัตถุยังสามารถมีรหัสเพื่อตรวจสอบว่ามีไฟล์อยู่หรือถูกล็อก ฯลฯ เป็นเพียงรูปแบบของstackoverflow.com/a/3157182/632951
Pacerier

1
"พวกเขาขัดขวางการไหลของตรรกะ" ข้อยกเว้นมีผลมากหรือน้อยgoto
peterchaula

22

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


17

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

ต่อไปนี้เป็นบทความที่กล่าวถึงการเปรียบเทียบและเปรียบเทียบเทคนิคทั้งสอง:

มีลิงก์ที่ดีในลิงก์ที่สามารถให้คุณอ่านเพิ่มเติมได้


16

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

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

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

Employee EmpOfMonth = GetEmployeeOfTheMonth();

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

Employee EmpOfMonth; 
if (getEmployeeOfTheMonth(ref EmpOfMonth) == ERROR)
    // code to Handle the error here

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


ตอบโจทย์มาก! แก้ปัญหานอกกรอบทันเวลา!
Cristian E.

11

ที่ผ่านมาฉันเข้าร่วมค่าย errorcode (เขียนโปรแกรม C มากเกินไป) แต่ตอนนี้ฉันได้เห็นแสงสว่างแล้ว

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

ดังนั้นใช้ข้อยกเว้น แต่ใช้อย่างชาญฉลาด และพวกเขาจะเป็นเพื่อนของคุณ

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


1
yap C ทิ้งนิสัยบางอย่างไว้ในตัวเราทุกคน;)
Jorge Ferreira

11

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

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

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

try {
    // Normal things are happening logic
catch (// A problem) {
    // Something went wrong logic
}

... เป็นที่นิยมสำหรับสิ่งนี้:

// Some normal stuff logic
if (errorCode means error) {
    // Some stuff went wrong logic
}
// Some normal stuff logic
if (errorCode means error) {
    // Some stuff went wrong logic
}
// Some normal stuff logic
if (errorCode means error) {
    // Some stuff went wrong logic
}

มีสิ่งเล็กน้อยอื่น ๆ เกี่ยวกับข้อยกเว้นที่ดีเช่นกัน การมีตรรกะเงื่อนไขจำนวนมากเพื่อติดตามว่าเมธอดใด ๆ ที่ถูกเรียกในฟังก์ชันมีการส่งคืนรหัสข้อผิดพลาดหรือไม่และส่งคืนรหัสข้อผิดพลาดนั้นให้สูงขึ้นเป็นแผ่นหม้อไอน้ำจำนวนมาก ในความเป็นจริงจานหม้อไอน้ำจำนวนมากอาจผิดพลาดได้ ฉันมีความเชื่อในระบบการยกเว้นของภาษาส่วนใหญ่มากกว่าที่ฉันทำรังหนูของคำสั่ง if-else-if-else ที่เฟรดเขียนว่า 'Fresh-out-of-college' และฉันมีสิ่งที่ดีกว่ามากมายที่ต้องทำ ด้วยเวลาของฉันมากกว่าการตรวจสอบรหัสกล่าวว่ารังของหนู


8

คุณควรใช้ทั้งสองอย่าง สิ่งที่เป็นในการตัดสินใจเมื่อใช้แต่ละคน

มีบางสถานการณ์ที่ข้อยกเว้นเป็นทางเลือกที่ชัดเจน :

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

  2. แต่เกี่ยวกับสถานการณ์ที่ 1 (ที่บางสิ่งบางอย่างที่ไม่คาดคิดเกิดขึ้นและ unhandleable คุณเพียงเข้าสู่ระบบ wan't มัน) ข้อยกเว้นจะมีประโยชน์เพราะคุณอาจจะเพิ่มข้อมูลตามบริบท ตัวอย่างเช่นถ้าฉันได้รับ SqlException ในตัวช่วยข้อมูลระดับล่างของฉันฉันจะต้องการตรวจจับข้อผิดพลาดนั้นในระดับต่ำ (ซึ่งฉันรู้คำสั่ง SQL ที่ทำให้เกิดข้อผิดพลาด) เพื่อที่ฉันจะได้จับข้อมูลนั้นและสร้างข้อมูลเพิ่มเติมอีกครั้ง . โปรดทราบคำวิเศษที่นี่: rethrow และไม่กลืน กฎข้อแรกของการจัดการข้อยกเว้น:ไม่กลืนข้อยกเว้น นอกจากนี้โปรดทราบว่าการจับภายในของฉันไม่จำเป็นต้องบันทึกอะไรเลยเพราะตัวจับด้านนอกจะมีการติดตามสแต็กทั้งหมดและอาจบันทึกได้

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

    ตัวอย่างหนึ่งจะเป็นลำดับของคำสั่ง SQL ภายในบล็อกธุรกรรม อีกครั้งนี่เป็นสถานการณ์ที่ "ไม่สามารถจัดการได้" แม้ว่าคุณจะตัดสินใจที่จะจับมัน แต่เนิ่น ๆ (ปฏิบัติในพื้นที่แทนที่จะเป็นฟองขึ้นไปด้านบน) แต่ก็ยังคงเป็นสถานการณ์ที่ร้ายแรงซึ่งผลลัพธ์ที่ดีที่สุดคือการยกเลิกทุกอย่างหรืออย่างน้อยก็แท้งครั้งใหญ่ เป็นส่วนหนึ่งของกระบวนการ
    (*) นี่เหมือนกับon error gotoที่เราใช้ใน Visual Basic รุ่นเก่า

  4. ในตัวสร้างคุณสามารถโยนข้อยกเว้นเท่านั้น

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

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

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

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

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

สรุปได้:

  • ฉันชอบใช้ข้อยกเว้นเมื่อฉันมีสถานการณ์ที่ไม่คาดคิดซึ่งไม่มีอะไรให้ทำมากนักและโดยปกติแล้วเราต้องการยกเลิกบล็อกโค้ดขนาดใหญ่หรือแม้แต่การดำเนินการหรือโปรแกรมทั้งหมด นี่ก็เหมือนกับ "on error goto" แบบเก่า

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

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

แต่เกี่ยวกับ GO ยังอนุญาตให้ส่งคืนค่าหลายค่าซึ่งเป็นสิ่งที่ช่วยได้มากในการใช้รหัสส่งคืนเนื่องจากคุณสามารถส่งคืนข้อผิดพลาดและอย่างอื่นได้พร้อมกัน บน C # / Java เราสามารถบรรลุสิ่งนั้นได้โดยไม่ต้องใช้พารามิเตอร์ Tuples หรือ Generics (โปรดของฉัน) ซึ่งรวมกับ enums สามารถให้รหัสข้อผิดพลาดที่ชัดเจนแก่ผู้โทร:

public MethodResult<CreateOrderResultCodeEnum, Order> CreateOrder(CreateOrderOptions options)
{
    ....
    return MethodResult<CreateOrderResultCodeEnum>.CreateError(CreateOrderResultCodeEnum.NO_DELIVERY_AVAILABLE, "There is no delivery service in your area");

    ...
    return MethodResult<CreateOrderResultCodeEnum>.CreateSuccess(CreateOrderResultCodeEnum.SUCCESS, order);
}

var result = CreateOrder(options);
if (result.ResultCode == CreateOrderResultCodeEnum.OUT_OF_STOCK)
    // do something
else if (result.ResultCode == CreateOrderResultCodeEnum.SUCCESS)
    order = result.Entity; // etc...

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


4

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

ในกรณีอื่น ๆ ข้อยกเว้นอาจเป็นหนทางไป


4

ฉันอาจจะนั่งอยู่บนรั้วที่นี่ แต่ ...

  1. มันขึ้นอยู่กับภาษา
  2. ไม่ว่าคุณจะเลือกรุ่นใดให้สอดคล้องกับวิธีการใช้งาน

ใน Python การใช้ข้อยกเว้นถือเป็นการปฏิบัติตามมาตรฐานและฉันค่อนข้างพอใจที่จะกำหนดข้อยกเว้นของตัวเอง ใน C คุณไม่มีข้อยกเว้นเลย

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

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


4

เนื่องจากฉันทำงานกับ C ++ และมี RAII เพื่อให้ใช้งานได้อย่างปลอดภัยฉันจึงใช้ข้อยกเว้นเกือบทั้งหมด จะดึงข้อผิดพลาดในการจัดการออกจากโฟลว์โปรแกรมปกติและทำให้เจตนาชัดเจนยิ่งขึ้น

ฉันปล่อยให้ข้อยกเว้นสำหรับสถานการณ์พิเศษแม้ว่า หากฉันคาดหวังว่าจะมีข้อผิดพลาดเกิดขึ้นมากมายฉันจะตรวจสอบว่าการดำเนินการจะสำเร็จก่อนที่จะดำเนินการหรือเรียกใช้ฟังก์ชันเวอร์ชันที่ใช้รหัสข้อผิดพลาดแทน (Like TryParse())


3

ลายเซ็นของวิธีการควรสื่อสารให้คุณทราบว่าวิธีนี้ทำอย่างไร บางอย่างเช่น errorCode ยาว = getErrorCode (); อาจจะดี แต่ errorCode = fetchRecord (); สับสน


3

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

ฉันใช้เพื่อกำหนดข้อยกเว้นหลายประเภท (เช่น DataValidationException หรือ ProcessInterruptExcepion) และภายในข้อยกเว้นแต่ละข้อกำหนดคำอธิบายโดยละเอียดของแต่ละปัญหา

ตัวอย่างง่ายๆใน Java:

public class DataValidationException extends Exception {


    private DataValidation error;

    /**
     * 
     */
    DataValidationException(DataValidation dataValidation) {
        super();
        this.error = dataValidation;
    }


}

enum DataValidation{

    TOO_SMALL(1,"The input is too small"),

    TOO_LARGE(2,"The input is too large");


    private DataValidation(int code, String input) {
        this.input = input;
        this.code = code;
    }

    private String input;

    private int code;

}

ด้วยวิธีนี้ฉันใช้ข้อยกเว้นเพื่อกำหนดข้อผิดพลาดหมวดหมู่และรหัสข้อผิดพลาดเพื่อกำหนดข้อมูลโดยละเอียดเพิ่มเติมเกี่ยวกับปัญหา


2
เอิ่ม ... throw new DataValidationException("The input is too small")? ข้อดีอย่างหนึ่งของข้อยกเว้นคือการให้ข้อมูลโดยละเอียด
Eva

2

ข้อยกเว้นมีไว้สำหรับสถานการณ์พิเศษนั่นคือเมื่อไม่ได้เป็นส่วนหนึ่งของโฟลว์ปกติของโค้ด

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

แต่เมื่อมีสถานการณ์พิเศษเกิดขึ้นฉันเชื่อว่าข้อยกเว้นเป็นรูปแบบที่แสดงออกมากที่สุด

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

แต่ไปในทิศทางอื่นการใช้ข้อยกเว้นช่วยให้คุณสามารถสร้างสิ่งที่เป็นนามธรรมในระดับที่สูงขึ้นเพื่อจัดการข้อผิดพลาดของคุณซึ่งจะทำให้โค้ดของคุณแสดงออกและเป็นธรรมชาติมากยิ่งขึ้น ฉันอยากจะแนะนำการอ่านที่ดีเยี่ยมนี้ยัง underrated บทความโดย C ++ ผู้เชี่ยวชาญอังเดร Alexandrescu ในเรื่องของสิ่งที่เขาเรียกว่า "บังคับ": http://www.ddj.com/cpp/184403864 แม้ว่าจะเป็นบทความ C ++ แต่โดยทั่วไปแล้วหลักการก็สามารถใช้ได้และฉันได้แปลแนวคิดการบังคับใช้เป็น C # เรียบร้อยแล้ว


2

ก่อนอื่นฉันเห็นด้วยกับคำตอบของ Tom ที่ว่าสำหรับสิ่งของระดับสูงให้ใช้ข้อยกเว้นและสำหรับสิ่งระดับต่ำให้ใช้รหัสข้อผิดพลาดตราบใดที่ไม่ใช่ Service Oriented Architecture (SOA)

ใน SOA ซึ่งอาจมีการเรียกใช้เมธอดในเครื่องที่แตกต่างกันไม่สามารถส่งข้อยกเว้นผ่านสายได้ แต่เราใช้การตอบสนองต่อความสำเร็จ / ล้มเหลวโดยมีโครงสร้างดังนี้ (C #):

public class ServiceResponse
{
    public bool IsSuccess => string.IsNullOrEmpty(this.ErrorMessage);

    public string ErrorMessage { get; set; }
}

public class ServiceResponse<TResult> : ServiceResponse
{
    public TResult Result { get; set; }
}

และใช้สิ่งนี้:

public async Task<ServiceResponse<string>> GetUserName(Guid userId)
{
    var response = await this.GetUser(userId);
    if (!response.IsSuccess) return new ServiceResponse<string>
    {
        ErrorMessage = $"Failed to get user."
    };
    return new ServiceResponse<string>
    {
        Result = user.Name
    };
}

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


1

ฉันต้องการข้อยกเว้นสำหรับกรณีข้อผิดพลาดทั้งหมดยกเว้นเมื่อความล้มเหลวเป็นผลลัพธ์ที่ปราศจากข้อบกพร่องที่คาดหวังได้ของฟังก์ชันที่ส่งคืนประเภทข้อมูลดั้งเดิม เช่นการค้นหาดัชนีของสตริงย่อยภายในสตริงที่ใหญ่กว่ามักจะคืนค่า -1 หากไม่พบแทนที่จะเพิ่ม NotFoundException

การส่งคืนพอยน์เตอร์ที่ไม่ถูกต้องซึ่งอาจถูกยกเลิกการอ้างอิง (เช่นทำให้ NullPointerException ใน Java) ไม่เป็นที่ยอมรับ

การใช้รหัสข้อผิดพลาดที่เป็นตัวเลขหลายตัว (-1, -2) เนื่องจากค่าที่ส่งกลับสำหรับฟังก์ชันเดียวกันมักจะเป็นลักษณะที่ไม่ดีเนื่องจากไคลเอ็นต์อาจทำการตรวจสอบ "== -1" แทน "<0"

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

สิ่งที่ควรพิจารณาอีกประการหนึ่งคือเมื่อทำงานเป็นทีมซึ่งจะต้องขีดเส้นแบ่งที่ชัดเจนสำหรับผู้พัฒนาโรงเรียนในการตัดสินใจดังกล่าว เช่น "ข้อยกเว้นสำหรับสิ่งของระดับสูงรหัสข้อผิดพลาดสำหรับสิ่งของระดับต่ำ" เป็นเรื่องส่วนตัวมาก

ไม่ว่าในกรณีใดที่เป็นไปได้มากกว่าหนึ่งประเภทของข้อผิดพลาดเล็กน้อยซอร์สโค้ดไม่ควรใช้ลิเทอรัลตัวเลขเพื่อส่งคืนรหัสข้อผิดพลาดหรือจัดการกับมัน (ส่งคืน -7 ถ้า x == -7 ... ) แต่ ค่าคงที่ที่ระบุชื่อเสมอ (ส่งคืน NO_SUCH_FOO ถ้า x == NO_SUCH_FOO)


1

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

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

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


0

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


0

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

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

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


0

กฎทั่วไปของฉันคือ:

  • ข้อผิดพลาดเดียวอาจปรากฏในฟังก์ชัน: ใช้รหัสข้อผิดพลาด (เป็นพารามิเตอร์ของฟังก์ชัน)
  • อาจมีข้อผิดพลาดเฉพาะมากกว่าหนึ่งข้อ: ข้อยกเว้นการโยน

-1

รหัสข้อผิดพลาดยังใช้ไม่ได้เมื่อเมธอดของคุณส่งคืนสิ่งอื่นที่ไม่ใช่ค่าตัวเลข ...


3
อืมไม่. ดู win32 GetLastError () กระบวนทัศน์ ฉันไม่ได้ปกป้องมันเพียงแค่อ้างว่าคุณไม่ถูกต้อง
ทิม

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