"रूबी में अपवाद को कभी न बचाएं!"
शायद आपने यह पहले सुना हो। यह अच्छी सलाह है, लेकिन यह बहुत भ्रमित करने वाला है जब तक कि आप पहले से ही इसके बारे में नहीं जानते। आइए इस कथन को तोड़ें और देखें कि इसका क्या अर्थ है।
आप शायद जानते हैं कि रूबी में, आप इस तरह के अपवादों को बचा सकते हैं:
begin
do_something()
rescue => e
puts e # e is an exception object containing info about the error.
end
और आप त्रुटि का वर्गनाम प्रदान करके विशिष्ट त्रुटियों से बचाव कर सकते हैं।
begin
do_something()
rescue ActiveRecord::RecordNotFound => e
puts e # Only rescues RecordNotFound exceptions, or classes that inherit from RecordNotFound
end
रूबी में हर प्रकार का अपवाद सिर्फ एक वर्ग है। ऊपर के उदाहरण में, ActiveRecord::RecordNotFound केवल एक वर्ग का नाम है जो कुछ निश्चित परंपराओं का पालन करता है।
यह महत्वपूर्ण है क्योंकि जब आप RecordNotFound
. को बचाते हैं , आप इससे प्राप्त होने वाले किसी भी अपवाद को भी बचाते हैं।
आपको अपवाद को बचाव क्यों नहीं करना चाहिए
Exception
को बचाने में समस्या यह है कि यह वास्तव में हर अपवाद को बचाता है जो Exception
. से विरासत में मिला है . जो है.... वो सब!
यह एक समस्या है क्योंकि रूबी द्वारा आंतरिक रूप से उपयोग किए जाने वाले कुछ अपवाद हैं। उनका आपके ऐप से कोई लेना-देना नहीं है, और उन्हें निगलने से बुरी चीजें होंगी।
यहाँ कुछ बड़े हैं:
-
SignalException::Interrupt - अगर आप इसे बचाते हैं, तो आप कंट्रोल-सी दबाकर अपने ऐप से बाहर नहीं निकल सकते।
-
ScriptError::SyntaxError - सिंटैक्स त्रुटियों को निगलने का अर्थ है कि
puts("Forgot something)
. जैसी चीज़ें चुपचाप विफल हो जाएगा। -
NoMemoryError - जानना चाहते हैं कि क्या होता है जब आपका प्रोग्राम सभी रैम का उपयोग करने के बाद भी चलता रहता है? मैं भी नहीं।
begin
do_something()
rescue Exception => e
# Don't do this. This will swallow every single exception. Nothing gets past it.
end
मैं अनुमान लगा रहा हूं कि आप वास्तव में इनमें से किसी भी सिस्टम-स्तरीय अपवाद को निगलना नहीं चाहते हैं। आप केवल अपने सभी एप्लिकेशन स्तर की त्रुटियों को पकड़ना चाहते हैं। अपवादों के कारण आपका कोड आया।
सौभाग्य से, इसका एक आसान तरीका है।
इसके बजाय StandardError बचाव करें
वे सभी अपवाद जिनकी आपको परवाह होनी चाहिए StandardError
. से इनहेरिट करें . ये हमारे पुराने दोस्त हैं:
-
NoMethodError - जब आप एक ऐसी विधि को लागू करने का प्रयास करते हैं जो मौजूद नहीं है
-
लेखन त्रुटि -
1 + ""
. जैसी चीज़ों के कारण -
रनटाइम त्रुटि - अच्छे पुराने RuntimeError को कौन भूल सकता है?
इस तरह की त्रुटियों से बचाव के लिए, आप StandardError
. को बचाना चाहेंगे . आप इसे कुछ इस तरह लिखकर कर सकते हैं:
begin
do_something()
rescue StandardError => e
# Only your app's exceptions are swallowed. Things like SyntaxErrror are left alone.
end
लेकिन रूबी ने इसे उपयोग के लिए बहुत आसान बना दिया है।
जब आप अपवाद वर्ग को बिल्कुल निर्दिष्ट नहीं करते हैं, तो रूबी मानता है कि आपका मतलब मानक त्रुटि है। तो नीचे दिया गया कोड उपरोक्त कोड के समान है:
begin
do_something()
rescue => e
# This is the same as rescuing StandardError
end
कस्टम अपवादों को StandardError से इनहेरिट करना चाहिए
तो यदि आप अपने स्वयं के कस्टम अपवाद बना रहे हैं तो इसका आपके लिए क्या अर्थ है?
इसका मतलब है कि आपको हमेशा StandardError
. से इनहेरिट करना चाहिए , और कभी भी Exception
. से नहीं . अपवाद से विरासत खराब है क्योंकि यह बचाव के अपेक्षित व्यवहार को तोड़ देता है। लोग सोचेंगे कि वे सभी एप्लिकेशन-स्तरीय त्रुटियों से बचाव कर रहे हैं, लेकिन आप बस आगे बढ़ जाएंगे।
class SomethingBad < StandardError
end
raise SomethingBad
अपवाद वृक्ष
चूंकि रूबी के अपवाद एक वर्ग विरासत में लागू किए गए हैं, इसलिए इसे निर्धारित करना मददगार हो सकता है। रूबी के मानक पुस्तकालय के साथ शिप करने वाले अपवाद वर्गों की सूची नीचे दी गई है। रेल जैसे तृतीय-पक्ष रत्न इस चार्ट में अतिरिक्त अपवाद वर्ग जोड़ेंगे, लेकिन वे सभी इस सूची में किसी न किसी वर्ग से प्राप्त होंगे।
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