मैंने इसके बारे में सोचा और एक उदाहरण के साथ नहीं आ सका। कोई व्यक्ति अपवाद क्यों पकड़ना चाहता है और इसके बारे में कुछ भी नहीं करना चाहता है। क्या आप एक उदाहरण दे सकते हैं? शायद यह सिर्फ कुछ है जो कभी नहीं किया जाना चाहिए।
मैंने इसके बारे में सोचा और एक उदाहरण के साथ नहीं आ सका। कोई व्यक्ति अपवाद क्यों पकड़ना चाहता है और इसके बारे में कुछ भी नहीं करना चाहता है। क्या आप एक उदाहरण दे सकते हैं? शायद यह सिर्फ कुछ है जो कभी नहीं किया जाना चाहिए।
जवाबों:
मैं यह हर समय डी में रूपांतरण त्रुटियों जैसी चीजों के साथ करता हूं:
import std.conv, std.stdio, std.exception;
void main(string[] args) {
enforce(args.length > 1, "Usage: foo.exe filename");
double[] nums;
// Process a text file with one number per line into an array of doubles,
// ignoring any malformed lines.
foreach(line; File(args[1]).byLine()) {
try {
nums ~= to!double(line);
} catch(ConvError) {
// Ignore malformed lines.
}
}
// Do stuff with nums.
}
उस ने कहा, मुझे लगता है कि सभी कैच ब्लॉक्स में कुछ होना चाहिए , भले ही वह कुछ सिर्फ एक टिप्पणी हो जो यह समझाती हो कि आप अपवाद को क्यों अनदेखा कर रहे हैं।
संपादित करें: मैं इस बात पर भी जोर देना चाहता हूं कि यदि आप ऐसा कुछ करने जा रहे हैं, तो आपको केवल उस विशेष अपवाद को पकड़ने के लिए सावधान रहना चाहिए जिसे आप अनदेखा करना चाहते हैं। एक सादा पुराना catch {}
करना लगभग हमेशा एक बुरी बात है।
एक उदाहरण जहां मुझे लगता है कि कुछ भी किए बिना केवल अपवाद को निगल जाना ठीक है, यहां तक कि अपवाद को लॉग करना, लॉगिंग कोड के अंदर ही है।
यदि आपने कुछ लॉग करने की कोशिश की और अपवाद मिला तो बहुत कुछ नहीं है जो आप इसके बारे में कर सकते हैं:
यह आपको चुपचाप निगलने के "कम से कम बुराई" विकल्प के साथ छोड़ देता है, जिससे एप्लिकेशन को अपना मुख्य काम जारी रखने की अनुमति मिलती है, लेकिन इसके निवारण की क्षमता से समझौता करता है।
यदि एक अपवाद को एक ऑपरेशन द्वारा फेंक दिया गया था जो वैसे भी वैकल्पिक था, ऐसा करने के लिए कुछ भी नहीं हो सकता है। इसे लॉग करना उपयोगी नहीं हो सकता है। उस स्थिति में, आप बस इसे पकड़ना चाहते हैं और कुछ भी नहीं कर सकते हैं।
यदि आप ऐसा कर रहे हैं, तो एक टिप्पणी शामिल करें। हमेशा कुछ भी टिप्पणी करें जो बग की तरह दिखता है (एक switch
बयान में रिक्तता , खाली catch
ब्लॉक, एक स्थिति में असाइनमेंट)।
आप यह तर्क दे सकते हैं कि यह अपवादों का उचित उपयोग नहीं है, लेकिन यह एक और सवाल है।
catch
अधिकांश भाषाओं में खाली ब्लॉक एक कोड गंध हैं। मुख्य विचार असाधारण स्थितियों के लिए अपवादों का उपयोग करना है न कि उनका तार्किक नियंत्रण के लिए उपयोग करना। सभी अपवादों को कहीं न कहीं संभालना होगा।
इस दृष्टिकोण को लेने के परिणामस्वरूप, जब आप एक विशेष अनुप्रयोग परत को प्रोग्राम करते हैं, तो आपके पास कई विकल्प होते हैं:
यह वास्तव में कुछ भी नहीं करने के लिए कोई जगह नहीं छोड़ता है, खाली catch
ब्लॉक।
EDD TO ADD : मान लें कि आप किसी ऐसी भाषा में प्रोग्रामिंग कर रहे हैं, जहां अपवाद फेंकना प्रोग्राम लॉजिक (विकल्पों में से एक goto
) को नियंत्रित करने का सामान्य तरीका है । फिर catch
इस भाषा में लिखे गए प्रोग्राम में एक खाली else
ब्लॉक पारंपरिक भाषा में खाली ब्लॉक (या else
बिल्कुल भी ब्लॉक नहीं ) की तरह है। हालांकि, मेरा मानना है कि यह C #, जावा या C ++ विकास समुदायों द्वारा अनुशंसित प्रोग्रामिंग शैली नहीं है।
कुछ मामलों में, जावा को आपको एक अपवाद को संभालने की आवश्यकता होती है, जो पूरी तरह से किसी भी परिस्थिति में नहीं हो सकती है। इस कोड पर विचार करें:
try {
bytes[] hw = "Hello World".getBytes("UTF-8");
}
catch(UnsupportedCodingException e) {
}
जावा प्लेटफॉर्म के प्रत्येक कार्यान्वयन के लिए निम्न मानक वर्णों का समर्थन करना आवश्यक है।
...
UTF-8
आपके जावा प्लेटफ़ॉर्म को तोड़े बिना, इस अपवाद का कारण बनने का कोई तरीका नहीं है। तो इसे संभालने की जहमत क्यों? लेकिन आप कोशिश-कैच-क्लॉज को बस नहीं कर सकते।
throw new Error(e)
जाएगा कि मुझे कुछ भी याद नहीं है (या वास्तव में टूटे हुए प्लेटफॉर्म की रिपोर्ट करें)।
एक सामान्य नियम के रूप में, नहीं। आप या तो स्टैक अप अपवाद को फेंकना चाहते हैं, या जो हुआ उसे लॉग इन करें।
हालांकि, मैं अक्सर ऐसा करता हूं जब मैं तार को पार्स कर रहा हूं और संख्याओं में परिवर्तित कर रहा हूं (विशेषकर मैपिंग परियोजनाओं में जो कि उपयोग-एक बार और दूर की विविधता को फेंकते हैं)।
boolean isNonZeroNumber = false;
try {
if(StringUtils.isNotBlank(s) && new BigDecimal(s).compareTo(BigDecimal.ZERO) != 0) {
b = true;
}
} catch(NumberFormatException e) {
//swallow this exception; b stays false.
}
return b;
कुछ मामलों में, अपवाद बिल्कुल भी असाधारण नहीं है; वास्तव में, यह अपेक्षित है। इस उदाहरण पर विचार करें:
/* Check if the process is still alive; exitValue() throws an exception if it is */
try {
p.exitValue();
processPool.remove(p);
}
catch (IllegalThreadStateException e) { /* expected behaviour */ }
चूँकि java.lang.Process () में isAlive () मेथड नहीं है, यह जाँचने के एकमात्र तरीके के बारे में कि क्या यह अभी भी जीवित है, एक्ज़िटवैल्यू () को कॉल करना है, जो कि एक IllegalThreadStateEception को फेंकता है यदि प्रक्रिया अभी भी चल रही है।
मेरे विनम्र अनुभव में, शायद ही यह अच्छी बात है। आप लाभ भिन्न हो सकते हैं।
लगभग हर बार मैंने इसे हमारे कोड बेस में देखा है, ऐसा इसलिए हुआ है क्योंकि मैंने एक बग को ट्रैक किया है जिसे खाया अपवाद छिपा है। दूसरा तरीका, किसी भी कोड को उपलब्ध नहीं कराने के लिए, आवेदन में किसी त्रुटि को इंगित करने, या किसी अन्य कार्रवाई को करने का कोई तरीका नहीं है।
कभी-कभी, उदाहरण के लिए एपीआई परतों पर, आप अपवादों को अतीत में रहने नहीं देना चाहते हैं या नहीं पा सकते हैं, इसलिए उस स्थिति में, मैं सबसे सामान्य प्रयास करने और पकड़ने की कोशिश करता हूं, फिर उन पर लॉग ऑन करें। एक बार फिर, कम से कम डिबग / निदान सत्र को मौका दें।
आमतौर पर, यदि यह खाली होना चाहिए, तो कम से कम मैं किसी प्रकार का दावा करता हूं, इसलिए डिबग सत्र के दौरान कम से कम कुछ होता है। उस ने कहा, अगर मैं इसे संभाल नहीं सकता, तो मैं उन्हें पूरी तरह से छोड़ देता हूं।
आईएमओ एक जगह है जहां खाली कैच स्टेटमेंट ठीक हैं। परीक्षण मामलों में जहां आप एक अपवाद की उम्मीद करते हैं:
try
{
DoSomething(); //This should throw exception if everything works well
Assert.Fail('Expected exception was not thrown');
}
catch(<whatever exception>)
{
//Expected to get here
}
मेरा मानना है कि ऐसे कुछ मामले हैं जहां एक खाली कैच क्लॉज होना न्यायोचित है - ये ऐसे मामले हैं जब आप चाहते हैं कि कोड एक विशेष ऑपरेशन विफल होने पर बस चलता रहे। हालांकि, मुझे लगता है कि इस पैटर्न को आसानी से इस्तेमाल किया जा सकता है, इसलिए यह सुनिश्चित करने के लिए प्रत्येक उपयोग को बारीकी से जांचना चाहिए कि इसे संभालने का बेहतर तरीका नहीं है। विशेष रूप से, यह कभी भी नहीं किया जाना चाहिए यदि यह प्रोग्राम को असंगत स्थिति में छोड़ देता है या यदि यह बाद में कोड के कुछ अन्य भाग को विफल कर सकता है।
मुझे विश्वास नहीं है कि अपवाद होने पर कुछ स्तर की सतर्कता नहीं होती - क्या कोड को बेहतर बनाने के लिए प्रोग्रामिंग के लक्ष्यों में से एक नहीं होना चाहिए? यदि कोई अपवाद समय का 10% होता है, और आप इसके बारे में कभी नहीं जानते हैं, तो अपवाद हमेशा बुरा या बुरा होगा।
हालांकि, मैं दूसरी तरफ देखता हूं, कि अगर कोड के प्रसंस्करण में अपवाद कोई वास्तविक नुकसान नहीं है, तो उपयोगकर्ता को इसे क्यों उजागर करें। जो समाधान मैं आमतौर पर लागू करता हूं, वह मेरे लकड़हारे वर्ग द्वारा लॉग किया जा रहा है (जो कि हर एक कक्षा में है जो मैं कभी भी काम पर लिखता हूं)।
यदि यह एक सौम्य अपवाद है, तो मैं अपने लकड़हारे को एक कॉल करता हूं ।ebug () विधि; अन्यथा, Logger.Error () (और (शायद) फेंक)।
try
{
doWork();
}
catch(BenignException x)
{
_log.Debug("Error doing work: " + x.Message);
}
वैसे, मेरे लकड़हारा के मेरे कार्यान्वयन में, .Debug () पद्धति से कॉल करना केवल तभी लॉग करेगा जब मैं अपना App.Config फ़ाइल निर्दिष्ट करता हूं कि प्रोग्राम निष्पादन लॉग स्तर डीबग मोड में है।
अस्तित्व की जाँच एक अच्छा उपयोग मामला है:
// If an exception happens, it doesn't matter. Log the initial value or the new value
function logId(person) {
let id = 'No ID';
try {
id = person.data.id;
} catch {}
console.log(id);
}
एक और मामला है जब एक finally
खंड का उपयोग किया जाता है:
function getter(obj){}
function objChecker()
{
try
{
/* Check argument length and constructor type */
if (getter.length === 1 && getter.constructor === Function)
{
console.log("Correct implementation");
return true;
}
else
{
console.log("Wrong implementation");
return false;
}
}
catch(e)
{
}
finally
{
console.log(JSON.stringify(getter))
}
}
// Test the override of the getter method
getter = getter;
objChecker();
getter = [];
objChecker();
getter = {};
objChecker();
getter = RegExp;
objChecker();
getter = Function;
objChecker();
ईसीएमएस्क्रिप्ट में कैच बाइंडिंग के चूक की अनुमति देने का एक प्रस्ताव है जो इस और इसी तरह के उपयोग के मामलों से संबंधित है।
संदर्भ
एकमात्र समय जब मुझे वास्तव में कुछ ऐसा करने की आवश्यकता होती है, यह कंसोल ऐप के लिए लॉगिंग क्लास के साथ था। एक शीर्ष-स्तरीय वैश्विक कैच हैंडलर था जिसने STDOUT में त्रुटि का उत्सर्जन किया, त्रुटि को एक फ़ाइल में लॉग इन किया, फिर ऐप को> 0 त्रुटि कोड के साथ बंद कर दिया।
यहां समस्या यह थी कि कभी-कभी, फ़ाइल में लॉगिंग विफल रही। निर्देशिका अनुमतियाँ आपको फ़ाइल लिखने से रोकती हैं, फ़ाइल विशेष रूप से लॉक की गई थी, जो भी हो। अगर ऐसा हुआ, तो मैं अपवाद को उसी तरह से नहीं संभाल सकता था जो मेरे पास कहीं था (पकड़, संबंधित विवरण लॉग करें , एक बेहतर अपवाद प्रकार में लपेटें, आदि) क्योंकि अपवाद विवरण लॉग करने से लकड़हारा उसी कार्यों से गुजरता है (आदि एक फ़ाइल को लिखने की कोशिश कर रहा है) जो पहले ही विफल हो गई थी। जब वे फिर से विफल रहे ... आप देखें कि मैं कहाँ जा रहा हूँ। यह एक अनंत पाश में हो जाता है।
यदि आप कुछ प्रयास {} ब्लॉक छोड़ते हैं, तो आप एक संदेश बॉक्स में दिखाई देने वाले अपवाद के साथ समाप्त हो सकते हैं (न कि आप साइलेंट कॉन्फिग एप्लिकेशन के लिए क्या चाहते हैं)। तो उस विधि में जो लॉग फ़ाइल में लिखता है, मेरे पास एक खाली कैच हैंडलर है। यह त्रुटि को दफन नहीं करता है क्योंकि आप अभी भी> 0 त्रुटि कोड प्राप्त करते हैं, यह सिर्फ अनंत लूप को रोकता है और एप्लिकेशन को इनायत से बाहर निकलने की अनुमति देता है।
यह खाली है, यह बताते हुए बेशक एक टिप्पणी है।
(मैं यह पहले पोस्ट करने जा रहा था, मुझे बस गुमनामी में बह जाने का डर था। चूंकि मैं अकेला नहीं हूं, हालांकि)
यह उस स्थिति में ठीक है जब कुछ अनुक्रम को क्रियान्वित किया जाना चाहिए चाहे वह अंत में रखा गया सबसे महत्वपूर्ण टुकड़ा क्यों न हो।
उदाहरण के लिए। नियंत्रक के लिए मेजबान के गति नियंत्रण संचार में। आपातकालीन स्थितियों में आंदोलन को निरस्त करने, प्रक्षेपवक्र को रोकने, मोटर्स को निष्क्रिय करने, ब्रेक को सक्षम करने, एम्पलीफायर को निष्क्रिय करने और इसके बाद आपको बस पावर को मारना होगा। सभी क्रमिक रूप से होने चाहिए और यदि कोई एक कदम बाकी रहता है तो वैसे भी नुकसानदायक हार्डवेयर के स्वीकृत जोखिम के साथ भी निष्पादित किया जाना चाहिए। यदि उपरोक्त सभी विफल होते हैं, तो भी कहें कि मार बस पावर वैसे भी होना चाहिए।
किसी त्रुटि से उबरने के लिए सिस्टम संसाधनों को बंद करना
उदाहरण के लिए। यदि आप उस पृष्ठभूमि में एक सेवा चला रहे हैं जो उपयोगकर्ता को प्रतिक्रिया प्रदान नहीं करती है, तो आप उपयोगकर्ता को त्रुटि का संकेत नहीं देना चाहते हैं, लेकिन आपको एक सुंदर तरीके से उपयोग किए जा रहे संसाधनों को बंद करने की आवश्यकता है।
try
{
// execution code here
}
catch(Exception e)
{
// do nothing here
}
finally
{
// close db connection
// close file io resource
// close memory stream
// etc...
}
आदर्श रूप से, आप त्रुटियों को पकड़ने और उन्हें कंसोल पर या परीक्षण के लिए लॉग फ़ाइल में प्रिंट करने के लिए डिबग मोड में कैच का उपयोग करेंगे। उत्पादन परिवेश में, पृष्ठभूमि सेवाओं से आमतौर पर यह अपेक्षा की जाती है कि जब कोई त्रुटि डाली जाती है तो उपयोगकर्ता को बाधित नहीं करना चाहिए ताकि त्रुटि आउटपुट को दबा दिया जाए।