ที่ AppSignal เรามีการติดตามข้อผิดพลาดสำหรับแอปพลิเคชัน Ruby ในการดำเนินการดังกล่าว เราจะรวบรวมข้อยกเว้นทั้งหมดที่แอปพลิเคชันส่งถึงเรา และแจ้งให้นักพัฒนาทราบทันทีที่เกิดขึ้น
อาจเป็นเรื่องยากที่จะได้รับการจัดการข้อยกเว้นอย่างถูกต้อง ในบทความนี้ เราจะอธิบายวิธีการทำงาน ปัญหาที่เกิดจากการจัดการที่ไม่ดี และวิธีช่วยเหลือข้อยกเว้นอย่างเหมาะสม
การช่วยเหลือข้อยกเว้น
ด้วยการช่วยเหลือข้อยกเว้นใน Ruby คุณสามารถป้องกันไม่ให้แอปพลิเคชันของคุณหยุดทำงานในขณะที่มีสิ่งผิดปกติเกิดขึ้น ด้วย begin .. rescue บล็อก คุณสามารถระบุเส้นทางอื่นสำหรับแอปพลิเคชันของคุณเมื่อเกิดข้อผิดพลาด
นอกจากนี้ยังสามารถระบุข้อยกเว้นที่ควรได้รับการช่วยเหลือได้อีกด้วย เมื่อระบุคลาสข้อยกเว้น คลาสย่อยทั้งหมดของข้อยกเว้นนี้จะถูกบันทึกด้วย
ในตัวอย่างด้านบน คุณจะเห็นข้อยกเว้น Errno::ENOENT ถูกจับได้เมื่อพาเรนต์ SystemCallError กำลังได้รับการช่วยเหลือ
การช่วยเหลืออยู่สูงเกินไปในห่วงโซ่ข้อยกเว้น
สิ่งสำคัญคือต้องไม่ช่วยเหลือข้อยกเว้นสูงเกินไปในห่วงโซ่ข้อยกเว้น เมื่อคุณทำเช่นนี้ ข้อยกเว้นคลาสย่อยทั้งหมดจะถูกตรวจจับด้วย ทำให้การจับภาพของบล็อกช่วยเหลือกว้างเกินไป
นี่คือโปรแกรมที่อ่านไฟล์ปรับแต่งตามอาร์กิวเมนต์ที่ส่งไปยังโปรแกรม
ข้อความแสดงข้อผิดพลาดแจ้งว่าไม่สามารถอ่านไฟล์กำหนดค่าได้ แต่ปัญหาที่แท้จริงคือการพิมพ์โค้ดผิด
คลาสข้อยกเว้นเริ่มต้นที่ begin .. rescue จับได้ บล็อกคือ StandardError หากเราไม่ผ่านคลาสใดคลาสหนึ่ง Ruby จะช่วยเหลือ StandardError และข้อผิดพลาดคลาสย่อยทั้งหมด NoMethodError เป็นหนึ่งในข้อผิดพลาดเหล่านี้
การช่วยเหลือคลาสข้อยกเว้นเฉพาะจะช่วยป้องกันข้อผิดพลาดที่ไม่เกี่ยวข้องจากการแจ้งสถานะความล้มเหลวโดยไม่ตั้งใจ นอกจากนี้ยังอนุญาตให้มีข้อความแสดงข้อผิดพลาดแบบกำหนดเองที่เฉพาะเจาะจงมากขึ้นซึ่งเป็นประโยชน์ต่อผู้ใช้มากขึ้น
ข้อยกเว้นการช่วยเหลือ
มันอาจจะยังคงดึงดูดใจที่จะช่วยเหลือในระดับสูงในห่วงโซ่ข้อยกเว้น การช่วยเหลือข้อผิดพลาดทั้งหมดที่แอปพลิเคชันสามารถยกขึ้นจะป้องกันไม่ให้เกิดความล้มเหลว (เรามาแล้ว ความพร้อมในการทำงาน 100%!) อย่างไรก็ตาม มันอาจทำให้เกิดปัญหามากมายได้
คลาสข้อยกเว้นเป็นคลาสข้อยกเว้นหลักใน Ruby ข้อยกเว้นอื่นๆ ทั้งหมดเป็นคลาสย่อยของคลาสนี้ หากได้รับการช่วยเหลือ ข้อผิดพลาดทั้งหมดจะถูกตรวจจับ
ข้อยกเว้นสองประการที่แอปพลิเคชันส่วนใหญ่ไม่ต้องการช่วยเหลือคือ SignalException และ SystemExit
SignalException ถูกใช้เมื่อแหล่งภายนอกบอกให้แอปพลิเคชันหยุด นี่อาจเป็นระบบปฏิบัติการเมื่อต้องการปิดระบบ หรือผู้ดูแลระบบที่ต้องการหยุดแอปพลิเคชัน ตัวอย่าง
SystemExit จะใช้เมื่อ exit กำลังถูกเรียกจากแอปพลิเคชัน Ruby เมื่อสิ่งนี้เกิดขึ้น นักพัฒนาต้องการให้แอปพลิเคชันหยุด ตัวอย่าง
หากเราช่วยเหลือข้อยกเว้นและข้อยกเว้นเหล่านี้เกิดขึ้นในขณะที่แอปพลิเคชันกำลังเรียกใช้ begin ... rescue ... end บล็อกมันไม่สามารถออกได้
โดยทั่วไปแล้ว การช่วยเหลือ Exception ในสถานการณ์ปกติถือเป็นความคิดที่ไม่ดี เมื่อช่วยเหลือ Exception คุณจะป้องกันไม่ให้ SignalException และ SystemExit ทำงาน แต่ยังรวมถึง LoadError, SyntaxError และ NoMemoryError ด้วยเช่นกัน เป็นการดีกว่าที่จะช่วยเหลือข้อยกเว้นที่เฉพาะเจาะจงมากขึ้นแทน
ความล้มเหลวในการทดสอบ
เมื่อได้รับการช่วยเหลือข้อยกเว้น ให้ใช้ rescue Exception => e สิ่งอื่นนอกเหนือจากแอปพลิเคชันของคุณอาจเสียหายได้ ชุดทดสอบอาจซ่อนข้อผิดพลาดบางอย่างไว้จริงๆ
ในการยืนยันขั้นต่ำและ RSpec ที่ล้มเหลวจะทำให้เกิดข้อยกเว้นเพื่อแจ้งให้คุณทราบเกี่ยวกับการยืนยันที่ล้มเหลว ทำให้การทดสอบไม่ผ่าน เมื่อพวกเขาทำเช่นนั้น พวกเขาจะเพิ่มข้อยกเว้นแบบกำหนดเองของตนเอง ซึ่งจัดอยู่ในคลาสย่อยจากข้อยกเว้น
หากได้รับการช่วยเหลือในการทดสอบหรือในรหัสแอปพลิเคชัน อาจทำให้การยืนยันล้มเหลวได้
กำลังรอข้อยกเว้น
รหัสบางส่วนมีไว้เพื่อเพิ่มข้อยกเว้น ในชุดการทดสอบ คุณสามารถปิดเสียงข้อยกเว้นเพื่อไม่ให้การทดสอบล้มเหลวเมื่อยกขึ้น
อย่างไรก็ตาม นี่ไม่ได้ทดสอบว่ามีข้อยกเว้นเกิดขึ้นหรือไม่ เมื่อไม่มีข้อยกเว้น การทดสอบของคุณจะไม่สามารถบอกได้ว่าพฤติกรรมยังคงถูกต้องหรือไม่
เป็นไปได้ที่จะยืนยันว่ามีข้อยกเว้นเกิดขึ้นหรือไม่ และหากไม่ใช่ แสดงว่าข้อยกเว้นใดเกิดขึ้น
เพิ่มข้อยกเว้นอีกครั้ง
แอปพลิเคชันควรจับข้อยกเว้นในระดับที่สูงที่สุดในห่วงโซ่เป็นคลาส Exception เมื่อมีเหตุผลที่ดีเท่านั้น ตัวอย่างเช่น เมื่อมีการล้างข้อมูลก่อนออกจากบล็อกโค้ด เช่น การลบไฟล์ชั่วคราวที่จำเป็นต้องลบออกจริงๆ
คำแนะนำประการหนึ่งสำหรับเมื่อคุณจำเป็นต้องช่วยเหลือ Exception จริงๆ ให้เพิ่มใหม่อีกครั้งหลังจากที่คุณจัดการกับข้อผิดพลาดเสร็จแล้ว วิธีนี้ทำให้การจัดการข้อยกเว้น Ruby สามารถตัดสินชะตากรรมของกระบวนการในภายหลังได้
ไม่แน่ใจว่าจะช่วยเหลืออะไร
ตามที่กล่าวไว้ข้างต้น เป็นการดีที่จะระบุให้ชัดเจนว่าข้อผิดพลาดใดบ้างที่ต้องช่วยเหลือ
เมื่อคุณไม่แน่ใจว่าการดำเนินการสามารถทำให้เกิดข้อยกเว้นใดได้บ้าง การช่วยเหลือ StandardError อาจเป็นจุดเริ่มต้นที่ดี เรียกใช้โค้ดของคุณในสถานการณ์ต่างๆ และดูว่ามีข้อยกเว้นอะไรบ้าง
ทุกครั้งที่คุณพบข้อยกเว้นใหม่ ให้เพิ่มกรณีการช่วยเหลือเฉพาะสำหรับข้อยกเว้นเหล่านั้นหรือคลาสหลักที่เกี่ยวข้อง ระบุให้เจาะจงว่าควรช่วยเหลืออะไรมากกว่าช่วยเหลือข้อยกเว้นมากเกินไป
นี่เป็นการสรุปไพรเมอร์ของเราเกี่ยวกับการจัดการข้อยกเว้นใน Ruby แจ้งให้เราทราบที่ @AppSignal หากคุณต้องการทราบข้อมูลเพิ่มเติมหรือมีคำถามเฉพาะเจาะจง หากคุณต้องการได้รับข้อมูลเชิงลึกที่ดีขึ้นว่าแอปของคุณมีข้อยกเว้นเกิดขึ้นที่ใดและบ่อยแค่ไหน ลองใช้ AppSignal