Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Ruby

เข้าใจ Ruby: Exception vs StandardError - ความแตกต่างสำคัญ

"Never rescue Exception in Ruby!"

อาจได้ยินมาก่อน คำแนะนำดีแตสับสนถ้ายังไม่ในวงใน มาแยก statement นี้ดู

คุณรู้ว่าใน Ruby rescue exceptions ได้แบบนี้:

begin do_something() rescue => e puts e # e is an exception object containing info about the error. end 

Rescue specific errors โดยให้ classname ของ error:

begin do_something() rescue ActiveRecord::RecordNotFound => e puts e # Only rescues RecordNotFound exceptions, or classes that inherit from RecordNotFound end 

ทุกประเภท exception ใน Ruby แค่ class ตัวอย่าง ActiveRecord::RecordNotFound แค่ชื่อ class ที่ follow conventions

สำคัญเพราะเวลา rescue RecordNotFound ก็ rescue exceptions ที่ inherit จากมันด้วย

ทำไมไม่ควร Rescue Exception

ปัญหา rescue Exception คือมัน rescue ทุก exception ที่ inherit จาก Exception ซึ่งคือ....ทั้งหมด!

ปัญหาเพราะมี exceptions บางตัวใช้ internally โดย Ruby ไม่เกี่ยวกับ app ของคุณ นำกลับมาจะทำให้壞事发生

ตัวใหญ่ๆ:

  • SignalException::Interrupt - rescue นี้ไม่สามารถ exit app ด้วย control-c

  • ScriptError::SyntaxError - นำ syntax errors กลับคืน puts("Forgot something) fail silently

  • NoMemoryError - อยากรู้ไหมว่า program รันต่อหลังใช้ RAM หมด ผมไม่อยากรู้

begin do_something() rescue Exception => e # Don't do this. This will swallow every single exception. Nothing gets past it. end 

คุณไม่อยาก swallow system-level exceptions อยาก catch application-level errors จาก YOUR code

โชคดีมีวิธีง่าย

Rescue StandardError แทน

Exceptions ที่คุณควรสนใจ inherit จาก StandardError เพื่อนเก่า:

  • NoMethodError - raised ตอน invoke method ที่ไม่มี

  • TypeError - เกิดจาก 1 + ""

  • RuntimeError - ใครลืม RuntimeError ได้ไง?

Rescue errors เหล่านี้ rescue StandardError เขียนแบบนี้ได้:

begin do_something() rescue StandardError => e # Only your app's exceptions are swallowed. Things like SyntaxErrror are left alone. end 

แต่ Ruby ทำให้ง่ายกว่านี้

เวลาไม่ระบุ exception class Ruby assume ว่าหมายถึง StandardError โค้ดด้านล่าง identical กับด้านบน:

begin do_something() rescue => e # This is the same as rescuing StandardError end 

Custom Exceptions ควร Inherit จาก StandardError

หมายถึงอะไรถ้าสร้าง custom exceptions เอง?

ควร inherit จาก StandardError เสมอ และ อย่า inherit จาก Exception โดยเด็ดขาด Inherit จาก Exception แย่เพราะมันทำลาย expected behavior ของ rescue คนคิดว่ารescue all application-level errors แต่มันแค่ผ่านไป

class SomethingBad < StandardError end raise SomethingBad 

The Exception Tree

เพราะ Ruby exceptions implemented ใน class hierarchy ดู layout ช่วยได้ นี่คือ exception classes ที่มาพร้อม Ruby standard library Third-party gems เช่น rails เพิ่ม exception classes เพิ่ม แต่ทุกตัว inherit จาก class ใน list นี้

Exception NoMemoryError ScriptError LoadError NotImplementedError SyntaxError SignalException Interrupt StandardError ArgumentError IOError EOFError IndexError LocalJumpError NameError NoMethodError RangeError FloatDomainError RegexpError RuntimeError SecurityError SystemCallError SystemStackError ThreadError TypeError ZeroDivisionError SystemExit fatal