ใน Java สิ่งใดบ้างที่มีการตรวจสอบข้อยกเว้นที่ดีสำหรับ [ปิด]


14

ข้อยกเว้นที่ตรวจสอบของ Java ได้รับการกดที่ไม่ดีในช่วงหลายปีที่ผ่านมา สัญญาณบอกคือมันเป็นภาษาเดียวในโลกที่มี (ไม่ใช่ภาษา JVM อื่น ๆ เช่น Groovy และ Scala) ไลบรารี Java ที่มีชื่อเสียงเช่น Spring และ Hibernate ก็ไม่ควรใช้

ฉันพบการใช้งานส่วนตัวสำหรับพวกเขา ( ในตรรกะทางธุรกิจระหว่างเลเยอร์) แต่อย่างอื่นฉันก็ค่อนข้างยกเว้นการตรวจสอบการต่อต้าน

มีการใช้งานอื่นที่ฉันไม่เข้าใจหรือไม่?


ไลบรารีแกน Java ทั้งหมดใช้ข้อยกเว้นที่ตรวจสอบแล้วอย่างกว้างขวาง
Joonas Pulakka

3
@Joonas ฉันรู้และมันเจ็บปวด!
Brad Cupit

คำตอบ:


22

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

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

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

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

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

} catch (FileNotFoundException e) {
  throw new RuntimeException("Important file not present", e);
}

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

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

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


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


+1 นักออกแบบของ Spring ทำงานได้ดีในการแปลข้อยกเว้น Hibernate จำนวนมากให้เป็นข้อยกเว้นที่ไม่ได้ตรวจสอบ
Fil

FYI: Frank Sommers พูดถึงในหัวข้อนี้ว่าซอฟต์แวร์ป้องกันความผิดปกติมักอาศัยกลไกเดียวกัน บางทีคุณอาจแบ่งคำตอบของคุณออกเป็นคดีที่กู้คืนได้และคดีที่ร้ายแรง
rong wong

@rwong คุณช่วยอธิบายรายละเอียดสิ่งที่คุณมีในใจได้ไหม?

11

คุณได้คำตอบที่ดีสองข้อซึ่งอธิบายว่าข้อยกเว้นใดที่ตรวจสอบแล้วได้กลายเป็นจริง (+1 ทั้งคู่) แต่มันก็คุ้มค่าที่จะตรวจสอบสิ่งที่พวกเขาตั้งใจไว้ในทางทฤษฎีเพราะความตั้งใจนั้นคุ้มค่าจริง ๆ

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

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

data Foo a =
     Success a
   | DidNotWorkBecauseOfA
   | DidNotWorkBecauseOfB

สิ่งนี้บอกโปรแกรมเมอร์ว่าฟังก์ชันนั้นมีสองผลลัพธ์ที่เป็นไปได้นอกเหนือจากความสำเร็จ


+1 สำหรับการยกเว้นที่ตรวจสอบแล้วเกี่ยวกับความปลอดภัยของประเภท ฉันไม่เคยได้ยินความคิดนั้นมาก่อน แต่มันก็สมเหตุสมผลดี
Ixrec

11

IMO การตรวจสอบข้อยกเว้นเป็นการใช้งานที่ไม่สมบูรณ์ของสิ่งที่อาจเป็นความคิดที่ดีพอสมควร (ภายใต้สถานการณ์ที่แตกต่างกันโดยสิ้นเชิง - แต่จริงๆแล้วไม่ใช่ความคิดที่ดีแม้แต่ในสถานการณ์ปัจจุบัน)

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

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

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

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

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


ข้อความเริ่มต้นแรกของคุณเกี่ยวกับการจัดการกับข้อยกเว้นโดยตรงเป็นเท็จอยู่แล้ว คุณสามารถเพิ่มคำสั่ง throws และคำสั่ง throws นั้นอาจเป็นประเภท parent นอกจากนี้หากคุณไม่คิดว่าคุณจะต้องจัดการกับมันคุณสามารถแปลงเป็น RuntimeException แทน IDE โดยทั่วไปช่วยคุณในการทำงานทั้งสองอย่าง
Maarten Bodewes

2
@ Wowstead: ขอบคุณ - ฉันน่าจะระวังข้อความให้มากขึ้น ประเด็นก็คือไม่มากนักที่คุณจะต้องรับการยกเว้นตามที่เป็นอยู่นั้นคือทุกระดับของรหัสกลางจำเป็นต้องระวังทุกข้อยกเว้นที่อาจไหลผ่านมัน สำหรับส่วนที่เหลือ: การมีเครื่องมือที่ทำให้มันยุ่งและง่ายต่อการทำให้โค้ดของคุณไม่เปลี่ยนความจริงที่ว่ามันทำให้เลอะรหัส
Jerry Coffin

การตรวจสอบข้อยกเว้นมีไว้สำหรับภาระผูกพัน - ผลลัพธ์ที่คาดการณ์ได้และสามารถกู้คืนได้นอกเหนือจากความสำเร็จซึ่งแตกต่างจากความล้มเหลว - ปัญหาระดับต่ำหรือระบบที่คาดเดาไม่ได้ FileNotFound หรือข้อผิดพลาดในการเปิดการเชื่อมต่อ JDBC ทั้งสองถือว่าเป็นภาระผูกพันอย่างถูกต้อง น่าเสียดายที่นักออกแบบไลบรารี Java ทำข้อผิดพลาดทั้งหมด & กำหนดข้อยกเว้น IO และ SQL อื่น ๆ ทั้งหมดให้กับคลาส 'ที่ตรวจสอบ' เช่นกัน แม้สิ่งเหล่านี้จะไม่สามารถกู้คืนได้เกือบทั้งหมด literatejava.com/exceptions/ …
Thomas W

@owlstead: ข้อยกเว้นการยืมควรฟองเพียงผ่านชั้นกลางของสแต็คโทรถ้าพวกเขาจะโยนในกรณีที่คาดว่ารหัสโทรกลาง IMHO การตรวจสอบข้อยกเว้นจะเป็นสิ่งที่ดีหากผู้โทรต้องจับพวกเขาหรือระบุว่าพวกเขาคาดหวังหรือไม่ ข้อยกเว้นที่ไม่คาดคิดควรจะห่อโดยอัตโนมัติในประเภทที่ได้มาจากUnexpectedException RuntimeExceptionโปรดทราบว่า "การขว้าง" และ "ไม่ได้คาดหวัง" นั้นไม่ขัดแย้ง ถ้าfooพ่นBozExceptionและบริการโทรbarที่ไม่ได้หมายความว่ามันคาดว่าจะโยนbar BozException
supercat

10

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


4
แก้ไขง่าย: throws FileNotFoundException. แก้ไขยาก:catch (FileNotFoundException e) { throw RuntimeException(e); }
Thomas Eding

5

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

  • โมดูล A อาจถูกสร้างขึ้นที่ด้านบนของโมดูล B ที่
  • โมดูล B อาจถูกสร้างขึ้นที่ด้านบนของโมดูล C
  • โมดูล C อาจทราบวิธีระบุข้อผิดพลาดและ
  • โมดูล A อาจรู้วิธีจัดการกับข้อผิดพลาด

การแยกความกังวลออกมาเป็นเรื่องที่ดีเพราะตอนนี้ความรู้เกี่ยวกับข้อผิดพลาดที่อาจ จำกัด เฉพาะ A และ C ต้องกระจัดกระจายไปทั่ว B

มีการสนทนาที่ดีเกี่ยวกับข้อยกเว้นที่ถูกตรวจสอบใน Wikipedia

และ Bruce Eckel ก็มีบทความที่ดีเช่นกัน นี่คือคำพูด:

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

ฉันเชื่อว่าในกรณีของ C ++ หากวิธีการทั้งหมดมีthrowsข้อกำหนดข้อคุณสามารถมีการเพิ่มประสิทธิภาพที่ดี ฉันไม่เชื่อว่า Java มีข้อได้เปรียบเหล่านั้นอยู่ดีเนื่องจากRuntimeExceptionsไม่ได้รับการตรวจสอบ JIT ที่ทันสมัยควรจะสามารถปรับรหัสให้เหมาะสมอยู่ดี

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

บางทีมันอาจเป็นเรื่องน่าขันที่ Java ได้เผชิญกับปัญหาทั้งหมดนี้เมื่อมันสามารถตรวจสอบได้nullแทนซึ่งอาจมีค่ามากกว่านี้


ฮ่าฮ่าไม่เคยคิดเกี่ยวกับการตรวจสอบสิ่งที่เป็นโมฆะในการตัดสินใจที่พวกเขาไม่ได้ทำ ... แต่ในที่สุดฉันก็เข้าใจว่ามันไม่ใช่ปัญหาโดยธรรมชาติหลังจากทำงานใน Objective-C ซึ่งช่วยให้ nulls มีวิธีการที่เรียกว่า
Dan Rosenstark

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

5

ฉันรักข้อยกเว้น

อย่างไรก็ตามฉันรู้สึกสับสนตลอดเวลาจากการใช้งานที่ไม่ได้ใช้

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

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

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

  4. หากคุณกำลังเขียนบิต 'frameworky' ของโค้ดตรวจสอบให้แน่ใจว่าอินเทอร์เฟซเริ่มต้นทั้งหมดของคุณถูกเขียนเพื่อโยนข้อยกเว้นใหม่ของคุณเองตามความเหมาะสม ... และตรวจสอบให้แน่ใจว่าโคเดอร์ของคุณมีโค้ดตัวอย่างอยู่รอบ ๆ พ่น IOException แต่อินเทอร์เฟซที่พวกเขากำลังเขียนเพื่อต้องการโยน 'ReportingApplicationException'

เมื่อคุณครุ่นคิดถึงวิธีที่จะทำให้ข้อยกเว้นทำงานให้คุณคุณจะไม่มองย้อนกลับไป


2
+1 สำหรับคำแนะนำที่ดี นอกจากนี้หากเหมาะสมให้ใช้initCauseหรือเริ่มต้นข้อยกเว้นด้วยข้อยกเว้นที่ทำให้เกิดข้อยกเว้น ตัวอย่าง: คุณมียูทิลิตี้ I / O ที่คุณต้องการข้อยกเว้นหากการเขียนล้มเหลว อย่างไรก็ตามมีสาเหตุหลายประการที่การเขียนอาจล้มเหลว (ไม่สามารถเข้าถึงเข้าถึงข้อผิดพลาดการเขียน ฯลฯ ) โยนข้อยกเว้นที่กำหนดเองของคุณด้วยสาเหตุหนึ่งเพื่อไม่ให้กลืนต้นฉบับปัญหา
Michael K

3
ฉันไม่ต้องการหยาบคาย แต่สิ่งนี้เกี่ยวข้องกับข้อยกเว้นที่ตรวจสอบได้อย่างไร :)
palto

อาจจะเขียนใหม่เพื่อเขียนลำดับชั้นของตัวเองของการตรวจสอบข้อยกเว้น
Maarten Bodewes

4

ข้อยกเว้นที่ตรวจสอบอยู่ใน ADA

(คำเตือนโพสต์นี้มีความเชื่ออย่างยิ่งที่คุณอาจพบว่าต้องเผชิญ)

โปรแกรมเมอร์ไม่ชอบพวกเขาและบ่นหรือเขียนโค้ดการกลืนยกเว้น

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

การอ่านไฟล์อาจล้มเหลว การเรียก RPC อาจล้มเหลว เครือข่าย IO สามารถล้มเหลว ข้อมูลสามารถจัดรูปแบบผิดเมื่อแยกวิเคราะห์

"เส้นทางที่มีความสุข" สำหรับรหัสนั้นง่าย

ฉันรู้จักผู้ชายคนหนึ่งในมหาวิทยาลัยที่สามารถเขียนโค้ด "เส้นทางที่มีความสุข" ที่ยอดเยี่ยมได้ ไม่มีกรณีที่ขอบเคยทำงาน ทุกวันนี้เขาทำ Python สำหรับ บริษัท โอเพ่นซอร์ส Nuff กล่าวว่า.

หากคุณไม่ต้องการจัดการข้อยกเว้นที่เลือกไว้สิ่งที่คุณพูดจริงๆคือ

While I'm writing this code, I don't want to consider obvious failure modes.

The User will just have to like the program crashing or doing weird things.

But that's okay with me because 

I'm so much more important than the people who will have to use the software

in the real, messy, error-prone world.

After all, I write the code once, you use it all day long.

ดังนั้นการตรวจสอบข้อยกเว้นจะไม่ถูกชอบโดยโปรแกรมเมอร์เพราะมันหมายถึงการทำงานมากขึ้น

แน่นอนว่าคนอื่นอาจต้องการงานที่ทำ

พวกเขาอาจต้องการคำตอบที่ถูกต้องแม้ว่าไฟล์เซิร์ฟเวอร์จะล้มเหลว / USB stick ตาย

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

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


6
พูดจาโผงผางดีคุณไปถึงที่นั่น
อดัมเลียร์

2
+1 "ไม่มีคดีขอบเลยวันนี้เขาทำ Python ให้กับ บริษัท โอเพ่นซอร์ส Nuff กล่าว" คลาสสิก
NimChimpsky

1
@palto: Java บังคับให้คุณพิจารณาเส้นทางที่ไม่ใช่เรื่องง่าย นั่นคือความแตกต่างที่ยิ่งใหญ่ สำหรับ C # คุณอาจพูดว่า "มีการบันทึกข้อยกเว้น" แล้วล้างมือให้สะอาด แต่โปรแกรมเมอร์มักผิดพลาด พวกเขาลืมสิ่งต่าง ๆ เมื่อฉันเขียนโค้ดฉันต้องการเตือน 100% ถึงรอยร้าวใด ๆ ที่คอมไพเลอร์สามารถแจ้งฉันได้
Thomas Eding

2
@ThomasEding Java บังคับให้ฉันจัดการกับข้อยกเว้นที่เรียกว่าเมธอด มันหายากมากที่จริง ๆ แล้วฉันต้องการทำอะไรกับมันในรหัสการโทรและโดยปกติแล้วฉันต้องการที่จะทำให้ข้อยกเว้นเกิดข้อผิดพลาดในการจัดการเลเยอร์ของแอปพลิเคชันของฉัน ฉันต้องแก้ไขด้วยการตัดข้อยกเว้นในข้อยกเว้นรันไทม์หรือฉันต้องสร้างข้อยกเว้นของตัวเอง โปรแกรมเมอร์ Lazy มีตัวเลือกที่สาม: เพียงเพิกเฉยเพราะฉันไม่สนใจ ด้วยวิธีนี้ไม่มีใครรู้ว่ามีข้อผิดพลาดเกิดขึ้นและซอฟต์แวร์มีข้อผิดพลาดแปลก ๆ อันที่สามนั้นไม่ได้เกิดขึ้นโดยมีข้อยกเว้นที่ไม่ได้ตรวจสอบ
palto

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

4

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

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

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


2
"การเพิกเฉยข้อยกเว้น" มักจะถูกต้องบ่อยครั้งที่การตอบสนองที่ดีที่สุดสำหรับข้อยกเว้นคือให้แอปหยุดทำงาน สำหรับทฤษฎีพื้นฐานสำหรับมุมมองนี้อ่านเบอร์แทรนด์เมเยอร์Object Oriented ก่อสร้างซอฟแวร์ เขาแสดงให้เห็นว่าหากมีการใช้ข้อยกเว้นอย่างถูกต้อง (สำหรับการละเมิดสัญญา) ว่ามีการตอบสนองที่ถูกต้องสองประการ: (1) ให้แอปหยุดทำงานหรือ (2) แก้ไขปัญหาที่ทำให้เกิดข้อยกเว้นและรีสตาร์ทกระบวนการ อ่านรายละเอียด Meyer; มันยากที่จะสรุปในความคิดเห็น
Craig Stuntz

1
@ Craig Stuntz โดยละเว้นข้อยกเว้นฉันหมายถึงการกลืนพวกเขา
Winston Ewert

อานั่นแตกต่างกัน ฉันเห็นด้วยที่คุณไม่ควรกลืนพวกเขา
Craig Stuntz

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

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