क्या सामान्य अपवादों को पकड़ना वास्तव में एक बुरी बात है?


57

मैं आमतौर पर अधिकांश कोड विश्लेषण चेतावनियों से सहमत हूं, और मैं उनका पालन करने की कोशिश करता हूं। हालाँकि, मैं इसके साथ कठिन समय बिता रहा हूँ:

CA1031: सामान्य अपवाद प्रकारों को न पकड़ें

मैं इस नियम के औचित्य को समझता हूं। लेकिन, व्यवहार में, अगर मैं अपवाद के अपवाद के बावजूद समान कार्रवाई करना चाहता हूं, तो मैं हर एक को विशेष रूप से क्यों संभालूंगा? इसके अलावा, अगर मैं विशिष्ट अपवादों को संभालता हूं, तो क्या होगा अगर कोड मैं भविष्य में एक नया अपवाद फेंकने के लिए परिवर्तनों को बुला रहा हूं? अब मुझे उस नए अपवाद को संभालने के लिए अपना कोड बदलना होगा। जबकि अगर मैंने बस Exceptionअपना कोड पकड़ा है तो उसे बदलना नहीं है।

उदाहरण के लिए, अगर फू बार को बुलाता है, और फू को बार द्वारा फेंके गए अपवाद के प्रकार की परवाह किए बिना प्रसंस्करण को रोकने की आवश्यकता है, तो क्या मैं पकड़े जाने वाले अपवाद के प्रकार के बारे में विशिष्ट होने में कोई फायदा है?

शायद एक बेहतर उदाहरण:

public void Foo()
{
    // Some logic here.
    LogUtility.Log("some message");
}

public static void Log()
{
    try
    {
        // Actual logging here.
    }
    catch (Exception ex)
    {
        // Eat it. Logging failures shouldn't stop us from processing.
    }
}

यदि आप यहां सामान्य अपवाद नहीं पकड़ते हैं, तो आपको हर प्रकार के अपवाद को पकड़ना होगा। पैट्रिक का एक अच्छा बिंदु है जिसे OutOfMemoryExceptionइस तरह से नहीं निपटा जाना चाहिए। तो क्या होगा अगर मैं हर अपवाद को अनदेखा करना चाहता हूं लेकिन OutOfMemoryException?


12
किस बारे में OutOfMemoryException? सब कुछ के रूप में एक ही हैंडलिंग कोड?
पैट्रिक

@ पैट्रिक अच्छा बिंदु। मैंने आपके प्रश्न को कवर करने के लिए अपने प्रश्न में एक नया उदाहरण जोड़ा।
बॉब हॉर्न

1
सामान्य अपवादों को पकड़ना उतना ही बुरा है जितना कि सामान्य बयान देना कि आप सभी को क्या करना चाहिए। आम तौर पर कोई एक आकार-फिट-सब कुछ के लिए दृष्टिकोण नहीं है।

4
OutOfMemoryErrorException
पैट्रिक

Ctrl-Alt-Del जैसे कीबोर्ड अपवादों के बारे में क्या?
मावग २ M

जवाबों:


33

ये नियम आम तौर पर एक अच्छा विचार है और इस प्रकार इसका पालन किया जाना चाहिए।

लेकिन याद रखें ये सामान्य नियम हैं। वे सभी स्थितियों को कवर नहीं करते हैं। वे सबसे आम स्थितियों को कवर करते हैं। यदि आपके पास एक विशिष्ट स्थिति है और आप यह तर्क दे सकते हैं कि आपकी तकनीक बेहतर है (और आपको ऐसा करने के लिए अपने तर्क को स्पष्ट करने के लिए कोड में एक टिप्पणी लिखने में सक्षम होना चाहिए) तो ऐसा करें (और फिर इसे समीक्षित करें)।

तर्क के काउंटर पक्ष पर।

मैं ऐसा करने के लिए एक अच्छी स्थिति के रूप में आपके उदाहरण को ऊपर नहीं देखता हूं। यदि लॉगिंग सिस्टम विफल हो रहा है (संभवत: कुछ अन्य अपवाद को लॉग कर रहा है) तो मैं शायद नहीं चाहता कि एप्लिकेशन जारी रहे। आउटपुट से बाहर निकलें और प्रिंट करें ताकि उपयोगकर्ता देख सके कि क्या हुआ था।


2
सहमत होना। बहुत कम से कम , अब जब नियमित रूप से लॉगिंग ऑफ़लाइन है तो कुछ इस तरह का प्रावधान करें कि कुछ और तरह के डिबगिंग आउटपुट दें, अगर कुछ और नहीं तो STDERR को।
शादुर

6
मैंने आप दोनों को उकसाया, लेकिन मुझे लगता है कि आप डेवलपर्स की तरह सोच रहे हैं, उपयोगकर्ताओं के नहीं। एक उपयोगकर्ता आमतौर पर परवाह नहीं करता है कि क्या लॉगिंग हो रही है, इसलिए जब तक एप्लिकेशन प्रयोग करने योग्य है।
मग

1
दिलचस्प है, क्योंकि log4net स्पष्ट रूप से एप को रोकना नहीं चाहता है क्योंकि लॉगिंग विफल हो जाती है। और मुझे लगता है कि यह इस बात पर निर्भर करता है कि आप क्या कर रहे हैं; सुरक्षा ऑडिट, सुनिश्चित करें कि प्रक्रिया को मार दें। लेकिन डिबग लॉग? यह महत्वपूर्ण नहीं है।
एंडी

1
@Andy: हां सब कुछ निर्भर करता है कि आप क्या कर रहे हैं।
मार्टिन यॉर्क

2
आप उन्हें क्यों नहीं समझते? और क्या आपको ऐसा करने का प्रयास नहीं करना चाहिए?
मग

31

हां, सामान्य अपवादों को पकड़ना बुरी बात है। एक अपवाद का आमतौर पर मतलब है कि कार्यक्रम वह नहीं कर सकता है जो आपने इसे करने के लिए कहा था।

कुछ अपवाद भी है कि आप में से कुछ प्रकार के होते हैं सकता है संभाल:

  • घातक अपवाद : स्मृति से बाहर, स्टैक ओवरफ्लो आदि। कुछ अलौकिक बल ने आपके ब्रह्मांड को गड़बड़ कर दिया है और प्रक्रिया पहले से ही मर रही है। आप स्थिति को बेहतर नहीं बना सकते इसलिए बस हार मान लें
  • अपवाद को फेंक दिया गया क्योंकि आपके द्वारा उपयोग किए जा रहे कोड में बग : उन्हें संभालने की कोशिश न करें, बल्कि समस्या के स्रोत को ठीक करें। प्रवाह नियंत्रण के लिए अपवादों का उपयोग न करें
  • असाधारण स्थिति : केवल इन मामलों में अपवाद को संभालें। यहां हम शामिल कर सकते हैं: नेटवर्क केबल अनप्लग्ड, इंटरनेट कनेक्शन ने काम करना बंद कर दिया, अनुमतियाँ गायब हैं, आदि।

ओह, और एक सामान्य नियम के रूप में: यदि आप नहीं जानते हैं कि यदि आप इसे पकड़ते हैं तो अपवाद के साथ क्या करना है, यह सिर्फ तेजी से विफल होना बेहतर है (अपवाद को कॉल करने वाले को छोड़ दें और इसे संभाल लें)


1
प्रश्न में विशिष्ट मामले के बारे में क्या? यदि लॉगिंग कोड में कोई बग है, तो अपवाद को अनदेखा करना शायद ठीक है, क्योंकि कोड जो वास्तव में मायने रखता है वह उससे प्रभावित नहीं होना चाहिए।
17

4
इसके बजाय लॉगिंग कोड में बग को ठीक क्यों करें?
विक्टर हर्डुगासी

3
विक्टर, यह शायद एक बग नहीं है। यदि डिस्क लॉग ऑन स्पेस से बाहर रहता है, तो क्या लॉगिंग कोड में एक बग है?
कार्सन 63000

4
@ Carson63000 - ठीक है, हाँ। लॉग नहीं लिखे जा रहे हैं, इसलिए: बग। निश्चित आकार के घूर्णन लॉग को लागू करें।
det

5
यह सबसे अच्छा उत्तर है, लेकिन यह एक महत्वपूर्ण पहलू है: सुरक्षा । कुछ अपवाद हैं जो बुरे लोगों के परिणामस्वरूप आपके कार्यक्रम को पूरा करने की कोशिश कर रहे हैं। यदि एक अपवाद को फेंक दिया जाता है जिसे आप संभाल नहीं पा रहे हैं, तो आप उस कोड पर अब भरोसा नहीं कर सकते। किसी को यह सुनना पसंद नहीं है कि उन्होंने कोड लिखा है कि बुरे लोगों को अंदर आने दो।
rivalk

15

सबसे ऊपरी बाहरी लूप में इनमें से एक को प्रिंट करने के लिए होना चाहिए, और फिर एक भयावह, हिंसक और कोई मौत नहीं होती (जैसा कि ऐसा नहीं होना चाहिए और किसी को सुनने की जरूरत है)।

अन्यथा आप आम तौर पर बहुत सावधान रहना चाहिए क्योंकि आप सबसे अधिक संभावना है कि इस स्थान पर होने वाली हर चीज का अनुमान नहीं लगाया है, और इसलिए सबसे अधिक संभावना है कि यह सही ढंग से इलाज नहीं करेगा। जितना संभव हो उतना विशिष्ट बनें ताकि आप केवल उन लोगों को पकड़ सकें जिन्हें आप जानते हैं कि क्या होगा, और उन लोगों को बुलबुले से पहले नहीं देखा जाना चाहिए जो उपर्युक्त शोर से मृत्यु तक हैं।


1
मैं इस सिद्धांत से सहमत हूं। लेकिन ऊपर मेरे लॉगिंग उदाहरण के बारे में क्या? क्या होगा यदि आप सरल लॉगिंग अपवादों को अनदेखा करना चाहते हैं और जारी रखते हैं? क्या आपको प्रत्येक अपवाद को पकड़ने की आवश्यकता है जिसे फेंका जा सकता है और अधिक गंभीर अपवाद बबल-अप को देते समय उनमें से प्रत्येक को संभाल सकता है?
बॉब हॉर्न

6
@ थोबॉर्न: उसको देखने के दो तरीके। हां, आप कह सकते हैं कि लॉगिंग विशेष रूप से महत्वपूर्ण नहीं है और यदि यह विफल रहता है, तो यह आपके ऐप को रोकना नहीं चाहिए। और यह एक उचित बिंदु है। लेकिन, क्या होगा यदि आपका आवेदन पांच महीने के लिए लॉग इन करने में विफल रहता है और आपको पता नहीं था? मैंने ऐसा होते देखा है। और फिर हमें लॉग की आवश्यकता थी। आपदा। मेरा सुझाव है कि आप सब कुछ करने के बारे में सोच सकते हैं कि लॉगिंग फेलिंग को रोकना बेहतर है, जब यह करता है तो इसे अनदेखा करना बेहतर होता है। (लेकिन आप उस पर एक आम सहमति नहीं बनने जा रहे हैं।)
पीडीआर

@pdr मेरे लॉगिंग उदाहरण में, मैं आम तौर पर ईमेल अलर्ट भेजता हूँ। या, हमारे पास लॉग्स को मॉनिटर करने के लिए सिस्टम हैं, और यदि लॉग सक्रिय रूप से पॉप्युलेट नहीं हो रहा है, तो हमारी सहायता टीम को अलर्ट मिलेगा। इसलिए हम अन्य तरीकों से लॉगिंग समस्या के बारे में जागरूक होंगे।
बॉब हॉर्न

@BusHorn अपने लॉगिंग उदाहरण के बजाय वंचित है - मुझे पता है कि सबसे लॉगिंग फ्रेमवर्क, किसी भी अपवाद को नहीं फेंकने के लिए महान लंबाई पर जाते हैं और उस तरह से आमंत्रित नहीं किया जाएगा (क्योंकि यह किसी भी "लॉग स्टेटमेंट फ़ाइल एक्स में लाइन एक्स पर हुआ) बेकार है )

@pdr मैंने लॉगबैक सूची (जावा) पर सवाल उठाया है कि लॉगिंग कॉन्फ़िगरेशन को कैसे विफल किया जाए अगर लॉगिंग कॉन्फ़िगरेशन विफल रहता है, तो बस इसलिए कि यह एसओ महत्वपूर्ण है क्योंकि हमारे पास लॉग हैं, और कोई भी मूक विफलता अस्वीकार्य है। एक अच्छा समाधान अभी भी लंबित है।

9

ऐसा नहीं है कि यह बुरा है, यह सिर्फ इतना है कि विशिष्ट कैच बेहतर हैं। जब आप विशिष्ट होते हैं, तो इसका मतलब है कि आप वास्तव में समझते हैं, अधिक संक्षेप में, आपका आवेदन क्या कर रहा है, और इस पर अधिक नियंत्रण है। सामान्य तौर पर, यदि आप ऐसी स्थिति में आते हैं, जहां आप सिर्फ एक अपवाद को पकड़ते हैं, तो उसे लॉग इन करें और जारी रखें, संभवतः कुछ बुरी चीजें हैं जो वैसे भी चल रही हैं। यदि आप विशेष रूप से उन अपवादों को पकड़ रहे हैं जिन्हें आप जानते हैं कि एक कोड ब्लॉक या विधि फेंक सकते हैं, तो एक उच्च संभावना है कि आप वास्तव में सिर्फ लॉगिंग और सर्वश्रेष्ठ के लिए उम्मीद करने के बजाय ठीक हो सकते हैं


5

दो संभावनाएं परस्पर अनन्य नहीं हैं।

एक आदर्श स्थिति में, आप अपनी पद्धति से उत्पन्न होने वाले सभी संभावित प्रकारों को पकड़ सकते हैं, उन्हें प्रति-अपवाद के आधार पर संभाल सकते हैं, और अंत में catchकिसी भी भविष्य या अज्ञात अपवादों को पकड़ने के लिए एक सामान्य खंड जोड़ सकते हैं। इस तरह आप दोनों दुनियाओं में सर्वश्रेष्ठ हो जाते हैं।

try
{
    this.Foo();
}
catch (BarException ex)
{
    Console.WriteLine("Foo has barred!");
}
catch (BazException ex)
{
    Console.WriteLine("Foo has bazzed!");
}
catch (Exception ex)
{
    Console.WriteLine("Unknown exception on Foo!");
    throw;
}

ध्यान रखें कि अधिक विशिष्ट अपवादों को पकड़ने के लिए, आपको उन्हें पहले रखना होगा।

संपादित करें: टिप्पणियों में बताए गए कारणों के लिए, अंतिम कैच में रीथ्रो जोड़ा गया।


2
रुको। आप कभी भी कंसोल और कैरी करने के लिए अज्ञात अपवाद को लॉग इन क्यों करना चाहेंगे? यदि यह अपवाद है कि आपको पता भी नहीं था कि कोड द्वारा फेंका जा सकता है, तो आप शायद सिस्टम विफलता के बारे में बात कर रहे हैं। इस परिदृश्य में ले जाना संभवतः एक बुरा विचार है।
pdr

1
@pdr निश्चित रूप से आपको लगता है कि यह एक विरोधाभासी उदाहरण है। बिंदु विशिष्ट और सामान्य दोनों अपवादों को पकड़ना था, न कि उन्हें कैसे संभालना था।
रोटेम

@ रॉटेम मुझे लगता है कि आपके पास यहां एक अच्छा जवाब है। लेकिन पीडीआर में एक बिंदु है। कोड, जैसा कि है, यह पकड़ने की तरह दिखता है और जारी रखना ठीक है। इस उदाहरण को देखकर, कुछ शुरुआती, सोच सकते हैं कि यह एक अच्छा तरीका है।
बॉब हॉर्न

वंचित या नहीं, यह आपके उत्तर को गलत बनाता है। जैसे ही आप आउट ऑफ़ मेमोरी और डिस्क फुल जैसे अपवादों को पकड़ना शुरू करते हैं और बस उन्हें निगलते हैं, आप साबित कर रहे हैं कि सामान्य अपवादों को पकड़ना वास्तव में बुरा क्यों है।
पीडीआर

1
यदि आप इसे लॉग करने के लिए केवल एक सामान्य अपवाद को पकड़ते हैं, तो आपको लॉगिंग के बाद इसे फिर से फेंक देना चाहिए।
विक्टर हर्डुगासी

5

मैं हाल ही में विचार कर रहा हूं, और मेरा अस्थायी निष्कर्ष यह है कि मात्र सवाल उठता है क्योंकि .NET अपवाद पदानुक्रम गंभीर रूप से गड़बड़ है।

उदाहरण के लिए ले लो,, नीच ArgumentNullExceptionजो हो सकता है एक अपवाद आप के लिए एक उचित उम्मीदवार हो नहीं है पकड़ने के लिए चाहते हैं, क्योंकि यह आदत कोड के बजाय एक वैध रनटाइम त्रुटि में एक बग से संकेत मिलता है। आह येस। तो NullReferenceException, सिवाय इसके कि सीधे NullReferenceExceptionसे प्राप्त होता SystemExceptionहै, इसलिए कोई बाल्टी नहीं है आप सभी "तार्किक त्रुटियों" को पकड़ने (या नहीं पकड़ने) में रख सकते हैं।

इसके बाद IMNSHO का प्रमुख बॉट है जो SEHExceptionव्युत्पन्न है (के माध्यम से ExternalException) SystemExceptionऔर इस प्रकार इसे एक "सामान्य" बनाते हैंSystemException जब आप एक प्राप्त करते हैंSEHException, तो आप एक डंप लिखना और जितनी जल्दी हो सके समाप्त करना चाहते हैं - और .NET 4 के साथ शुरू करना कम से कम कुछ SEH अपवादों को भ्रष्ट राज्य अपवाद माना जाता हैजिन्हें पकड़ा नहीं जाएगा। एक अच्छी बात, और एक ऐसा तथ्य जोCA1031नियम को और भी बेकार बना देता है, क्योंकि अब आपका आलसीcatch (Exception)इन सबसे खराब प्रकारों को वैसे भी पकड़ नहीं पाएगा।

फिर, ऐसा लगता है कि अन्य फ्रेमवर्क सामान असंगत रूप से या तो Exceptionसीधे या इसके माध्यम से प्राप्त होते हैं SystemException, जो गंभीरता से लूटने जैसी किसी चीज को पकड़ने-पकड़ने की कोशिश करते हैं।

श्री लिप्टर्ट द्वारा C#प्रसिद्धि का एक टुकड़ा है , जिसे वेक्सिंग अपवाद कहा जाता है , जहां वह अपवादों के कुछ उपयोगी वर्गीकरण को देता है: आप तर्क दे सकते हैं कि आप केवल "बहिर्मुखी" लोगों को पकड़ना चाहते हैं, सिवाय ... C#भाषा और .NET के डिज़ाइन के। फ्रेमवर्क अपवाद किसी भी रसीले तरीके से "केवल बहिर्जात लोगों को पकड़ना" असंभव बनाते हैं। (और, उदाहरण के लिए, बहुत अच्छी तरह से एक एपीआई के लिए एक पूरी तरह से सामान्य पुनर्प्राप्त करने योग्य त्रुटि OutOfMemoryExceptionहो सकती है जिसमें बफ़र्स को आवंटित करना पड़ता है जो किसी भी तरह बड़े होते हैं)

मेरे लिए निचला रेखा यह है, कि जिस तरह से C#ब्लॉक काम पकड़ता है और जिस तरह से फ्रेमवर्क अपवाद पदानुक्रम डिज़ाइन किया गया है, वह नियम CA1031पूरी तरह से बेकार है । यह "अपवादों को न निगलें" के मूल मुद्दे के साथ मदद करने का दिखावा करता है, लेकिन अपवादों को निगलने का शून्य है जो आप पकड़ते हैं, लेकिन आप जो करते हैं उसके साथ :

कर रहे हैं कम से कम 4 तरीके वैध तरीके से एक पकड़ा को संभालने के लिए Exception, और CA1031केवल अल्पज्ञता उनमें से एक (अर्थात् फिर से फेंक मामले) को संभालने के लिए लगता है।


एक साइड नोट के रूप में, अपवाद फ़िल्टर नामक एक C # 6 सुविधा है जो CA1031फिर से थोड़ा अधिक वैध बना देगा तब से आप ठीक से, ठीक से, उन अपवादों को फ़िल्टर कर पाएंगे जिन्हें आप पकड़ना चाहते हैं, और एक अनफ़िल्टर्ड लिखने का कम कारण है catch (Exception)


1
इसके साथ एक बड़ी समस्या OutOfMemoryExceptionयह है कि कोई अच्छा तरीका कोड नहीं हो सकता है यह सुनिश्चित करें कि यह "केवल" एक विशेष आवंटन की विफलता को इंगित करता है जिसे विफल होने के लिए तैयार किया गया था। यह संभव है कि कुछ अन्य गंभीर अपवाद फेंक दिए गए थे, और OutOfMemoryExceptionउस अन्य अपवाद से स्टैक अनइंडिंग के दौरान हुई। हो सकता है कि जावा अपने "ट्राय-विथ-रिसोर्सेज" के साथ पार्टी में देर से आया हो, लेकिन यह .NET के मुकाबले थोड़ा सा बेहतर होने के दौरान अपवादों को संभालता है।
सुपरकैट

1
@supercat - काफी हद तक सही है, लेकिन यह किसी भी अन्य सामान्य सिस्टम अपवाद के बहुत अधिक सच है, जब सामान किसी भी अंत में खराब हो जाता है।
मार्टिन बा

1
यह सच है, लेकिन एक (और आम तौर पर) finallyअपवादों के खिलाफ गार्ड को ब्लॉक कर सकते हैं कि कोई वास्तविक रूप से इस तरह से घटित होने की उम्मीद कर सकता है कि मूल और नए अपवाद दोनों लॉग हो जाते हैं। दुर्भाग्य से, ऐसा करने से अक्सर मेमोरी आवंटन की आवश्यकता होती है, जो स्वयं की विफलताओं का कारण बन सकता है।
सुपरकैट

4

Pokemon अपवाद हैंडलिंग (सभी को पकड़ना होगा!) निश्चित रूप से हमेशा खराब नहीं होता है। जब एक ग्राहक के लिए एक विधि को उजागर करना, विशेष रूप से एक अंत उपयोगकर्ता को अपने आवेदन दुर्घटना और जलने के बजाय कुछ भी और सब कुछ पकड़ने के लिए अक्सर बेहतर होता है।

आम तौर पर हालांकि वे जहाँ आप कर सकते हैं बचा जाना चाहिए। जब तक आप अपवाद के प्रकार के आधार पर विशिष्ट कार्रवाई नहीं कर सकते हैं, तो इसे संभालना बेहतर है और अपवाद को बुलबुला करने की अनुमति दें, फिर अपवाद को निगल लें या गलत तरीके से संभाल लें।

अधिक पढ़ने के लिए इस एसओ जवाब पर एक नज़र है ।


1
यह स्थिति (जब एक डेवलपर को पोकेमॉन ट्रेनर होना चाहिए) तब प्रकट होता है जब आप एक संपूर्ण सॉफ़्टवेयर खुद बना रहे होते हैं: आपने परतें, डेटाबेस कनेक्शन और उपयोगकर्ता का GUI बनाया। आपके ऐप को कनेक्टिविटी खो जाने, उपयोगकर्ता के फ़ोल्डर हटने, डेटा दूषित होने आदि जैसी स्थितियों से उबरना होगा। अंतिम उपयोगकर्ता क्रैश और जलने वाले ऐप को पसंद नहीं करते हैं। वे ऐसे ऐप्स पसंद करते हैं जो एक जलते हुए विस्फोट वाले कंप्यूटर पर काम कर सकें!
ब्रोकन_विंडो

मैंने अब तक इसके बारे में नहीं सोचा था, लेकिन पोकेमॉन में, आमतौर पर यह माना जाता है कि 'उन सभी को पकड़कर' आप बिल्कुल एक जैसा चाहते हैं, और इसे पकड़ने के लिए विशेष रूप से संभालना पड़ता है, जो इस वाक्यांश के सामान्य उपयोग के विपरीत है प्रोग्रामर के बीच।
मगस

2
@ मैगस: एक विधि की तरह LoadDocument(), यह अनिवार्य रूप से उन सभी चीजों की पहचान करने के लिए असंभव है जो गलत हो सकती हैं, लेकिन 99% अपवाद जो फेंक दिए जा सकते हैं , इसका सीधा सा मतलब होगा "दिए गए नाम के साथ किसी फ़ाइल की सामग्री की व्याख्या करना संभव नहीं था एक दस्तावेज, इसके साथ सौदा। " अगर कोई ऐसा कुछ खोलने की कोशिश करता है जो एक वैध दस्तावेज़ फ़ाइल नहीं है, तो यह एप्लिकेशन को क्रैश नहीं करना चाहिए और किसी अन्य खुले दस्तावेज़ को नहीं मारना चाहिए। ऐसे मामलों में पोकेमॉन एरर हैंडलिंग बदसूरत है, लेकिन मुझे कोई अच्छा विकल्प नहीं पता है।
सुपरकैट

@ सुपरकैट: मैं सिर्फ एक भाषाई बिंदु बना रहा था। हालाँकि, मुझे नहीं लगता कि अमान्य फ़ाइल सामग्री कुछ ऐसी ध्वनि है जो एक से अधिक प्रकार के अपवाद को फेंक दे।
मैगस

1
@Magus: यह सभी प्रकार के अपवादों को फेंक सकता है - यही समस्या है। किसी फ़ाइल में अमान्य डेटा के परिणामस्वरूप फेंके जाने वाले सभी प्रकार के अपवादों का अनुमान लगाना बहुत मुश्किल है। यदि कोई PokeMon हैंडलिंग का उपयोग नहीं करता है, तो एप्लिकेशन के मरने का एक जोखिम है क्योंकि उदाहरण के लिए फ़ाइल लोड हो रही थी जिसमें अंकों का असाधारण-लंबा तार एक स्थान पर था, जिसमें दशमलव-स्वरूपित 32-बिट पूर्णांक और एक संख्यात्मक अतिप्रवाह आवश्यक था। पार्सिंग लॉजिक।
सुपरकैट

1

सामान्य अपवाद को पकड़ना बुरा है क्योंकि यह आपके कार्यक्रम को अपरिभाषित स्थिति में छोड़ देता है। आप नहीं जानते कि सामान कहाँ गलत हुआ है, इसलिए आपको नहीं पता कि आपके कार्यक्रम ने वास्तव में क्या किया है या नहीं किया है।

जहां मैं किसी कार्यक्रम को बंद करते समय सभी को पकड़ने की अनुमति देता हूं। जब तक आप इसे ठीक से साफ कर सकते हैं। आपके द्वारा बंद किए गए प्रोग्राम के रूप में कष्टप्रद कुछ भी नहीं है जो सिर्फ एक त्रुटि संवाद फेंकता है जो कुछ भी नहीं करता है, लेकिन वहां बैठना, दूर नहीं जाना और अपने कंप्यूटर को बंद करने से रोकना है।

वितरित वातावरण में आपकी लॉग विधि बैकफ़ायर कर सकती है: एक सामान्य अपवाद को पकड़ने का मतलब यह हो सकता है कि आपका प्रोग्राम अभी भी लॉग-फ़ाइल पर एक लॉक रखता है जो अन्य उपयोगकर्ताओं को लॉग बनाने से रोकता है।


0

मैं इस नियम के औचित्य को समझता हूं। लेकिन, व्यवहार में, अगर मैं अपवाद के अपवाद के बावजूद समान कार्रवाई करना चाहता हूं, तो मैं हर एक को विशेष रूप से क्यों संभालूंगा?

जैसा कि दूसरों ने कहा है, यह वास्तव में मुश्किल है (यदि असंभव नहीं है) कुछ कार्रवाई की कल्पना करना है जिसे आप अपवाद के फेंकने के बावजूद लेना चाहते हैं। केवल एक उदाहरण ऐसी परिस्थितियां हैं जहां कार्यक्रम की स्थिति खराब हो गई है और किसी भी आगे की प्रक्रिया से समस्याएं हो सकती हैं (यह पीछे तर्क है Environment.FailFast)।

इसके अलावा, अगर मैं विशिष्ट अपवादों को संभालता हूं, तो क्या होगा अगर कोड मैं भविष्य में एक नया अपवाद फेंकने के लिए परिवर्तनों को बुला रहा हूं? अब मुझे उस नए अपवाद को संभालने के लिए अपना कोड बदलना होगा। जबकि अगर मैंने केवल अपवाद को पकड़ लिया तो मेरे कोड को बदलना नहीं है।

हॉबी कोड के लिए इसे पकड़ना ठीक है Exception, लेकिन प्रोफेशनल-ग्रेड कोड के लिए एक नए अपवाद प्रकार का परिचय उसी तरीके से किया जाना चाहिए, जिस तरह से सिग्नेचर सिग्नेचर में बदलाव किया जाता है, यानी इसे ब्रेकिंग चेंज माना जाता है। यदि आप इस दृष्टिकोण के लिए सदस्यता लेते हैं, तो यह तुरंत स्पष्ट है कि ग्राहक कोड को बदलने (या सत्यापित) करने के लिए वापस जाना केवल कार्रवाई का सही तरीका है।

उदाहरण के लिए, अगर फू बार को बुलाता है, और फू को बार द्वारा फेंके गए अपवाद के प्रकार की परवाह किए बिना प्रसंस्करण को रोकने की आवश्यकता है, तो क्या मैं पकड़े जाने वाले अपवाद के प्रकार के बारे में विशिष्ट होने में कोई फायदा है?

ज़रूर, क्योंकि आप सिर्फ फेंके गए अपवादों को नहीं पकड़ेंगे Bar। यह भी अपवाद होगा कि बार के ग्राहक या यहां तक ​​कि रनटाइम Barकॉल स्टैक पर उस समय के दौरान फेंक सकता है। एक अच्छी तरह से लिखे जाने वाले Barको अपने स्वयं के अपवाद प्रकार को परिभाषित करना चाहिए यदि आवश्यक हो ताकि कॉल करने वाले विशेष रूप से स्वयं द्वारा उत्सर्जित अपवादों को पकड़ सकें।

तो क्या होगा अगर मैं हर अपवाद को अनदेखा करना चाहता हूं लेकिन OutOfMemoryException?

IMHO यह अपवाद हैंडलिंग के बारे में सोचने का गलत तरीका है। आपको श्वेतसूची पर आधारित होना चाहिए (अपवाद अपवाद A और B को पकड़ें), न कि ब्लैकलाइस्ट पर (एक्स के अलावा सभी अपवादों को पकड़ें)।


यह अक्सर एक कार्रवाई को निर्दिष्ट करना संभव है, जो सभी अपवादों के लिए किया जाना चाहिए जो इंगित करता है कि कोई भी प्रयास बिना किसी साइड-इफ़ेक्ट और सिस्टम की स्थिति के प्रतिकूल प्रभाव के साथ विफल हो गया। उदाहरण के लिए, यदि कोई उपयोगकर्ता लोड करने के लिए एक दस्तावेज़ फ़ाइल का चयन करता है, तो एक प्रोग्राम "डिस्क फ़ाइल से डेटा के साथ दस्तावेज़ ऑब्जेक्ट बनाएं" नाम से गुजरता है, और यह विधि किसी विशेष कारण से विफल हो जाती है क्योंकि आवेदन का अनुमान नहीं था (लेकिन जो उपरोक्त मानदंडों को पूरा करता है), एप्लिकेशन को क्रैश करने के बजाय "दस्तावेज़ लोड करने में असमर्थ" संदेश प्रदर्शित करने के लिए उचित व्यवहार होना चाहिए।
सुपरकैट

दुर्भाग्य से, कोई मानक साधन नहीं है, जिसके द्वारा एक अपवाद इंगित कर सकता है कि सबसे महत्वपूर्ण बात ग्राहक कोड जानना चाहेगा - क्या यह सिस्टम की स्थिति के बारे में कुछ भी बुरा बताता है, जो अनुरोधित ऑपरेशन को करने में असमर्थता से परे होगा। इस प्रकार, भले ही ऐसी परिस्थितियाँ हों जहाँ सभी अपवादों को संभालना दुर्लभ हो, इस प्रकार कई परिस्थितियाँ हैं जिनमें कई अपवादों को उसी तरह से संभाला जाना चाहिए, और ऐसी कोई भी कसौटी नहीं है जो ऐसे सभी अपवादों से संतुष्ट हो, कुछ दुर्लभ लोगों द्वारा भी संतुष्ट होगी। अलग तरह से संभाला जाना चाहिए।
सुपरकैट

0

हो सकता है । हर नियम के अपवाद हैं, और किसी भी नियम का अनजाने में पालन नहीं किया जाना चाहिए। आप उदाहरण उदाहरण के लिए हो सकता है कि यह उन सभी उदाहरणों में से एक है जहां यह सभी अपवादों को निगलने के लिए समझ में आता है। उदाहरण के लिए यदि आप एक महत्वपूर्ण उत्पादन प्रणाली में अनुरेखण जोड़ना चाहते हैं, और आप पूरी तरह से सुनिश्चित करना चाहते हैं कि आप परिवर्तन ऐप के मुख्य कार्य को बाधित न करें।

हालाँकि , आपको उन सभी को चुपचाप अनदेखा करने का निर्णय लेने से पहले विफलता के संभावित कारणों के बारे में सावधानी से सोचना चाहिए। उदाहरण के लिए, यदि अपवाद का कारण क्या है:

  • लॉगिंग विधि में एक प्रोग्रामिंग त्रुटि जो इसे हमेशा एक विशेष अपवाद को फेंकने का कारण बनती है
  • कॉन्फ़िगरेशन में लॉगिंग फ़ाइल में एक अमान्य पथ
  • डिस्क भरा हुआ है

क्या आप तुरंत सूचित नहीं होना चाहते हैं कि यह समस्या मौजूद है, इसलिए आप इसे ठीक कर सकते हैं? अपवाद को निगलने का मतलब है कि आप कभी नहीं जानते कि कुछ गलत हो गया है।

कुछ समस्याएं (जैसे डिस्क भरी हुई है) भी एप्लिकेशन के अन्य भागों के विफल होने का कारण हो सकती है - लेकिन यह विफलता अभी लॉग नहीं हुई है, इसलिए आप कभी नहीं जानते हैं!


0

मैं इसे तकनीकी दृष्टिकोण के बजाय तार्किक दृष्टिकोण से संबोधित करना चाहूंगा,

अब मुझे उस नए अपवाद को संभालने के लिए अपना कोड बदलना होगा।

खैर, किसी को इसे संभालना होगा। वह विचार है। लाइब्रेरी कोड के लेखक नए अपवाद प्रकार जोड़ने के बारे में विवेकपूर्ण होंगे, क्योंकि यह ग्राहकों को तोड़ने की संभावना है, आपको इसका सामना अक्सर नहीं करना चाहिए।

आपका प्रश्न मूल रूप से "क्या होगा अगर मुझे परवाह नहीं है कि क्या गलत हो गया है? क्या मुझे वास्तव में यह पता लगाने की परेशानी से गुजरना होगा कि यह क्या था?"

यहाँ सौंदर्य हिस्सा है: नहीं, तुम नहीं।

"तो, क्या मैं सिर्फ दूसरा रास्ता देख सकता हूं और जो कुछ भी बुरा काम करता है वह स्वचालित रूप से कालीन के नीचे बह जाता है और इसके साथ किया जाता है?"

नहीं, यह नहीं है कि यह कैसे काम करता है।

मुद्दा यह है कि, संभावित अपवादों का संग्रह आपके द्वारा अपेक्षित संग्रह से हमेशा बड़ा होता है और आपकी स्थानीय छोटी समस्या के संदर्भ में रुचि रखता है। आप उन लोगों को संभालते हैं जो आप अनुमान लगाते हैं और यदि कुछ अप्रत्याशित होता है, तो आप इसे निगलने के बजाय उच्च स्तर के हैंडलर पर छोड़ देते हैं। यदि आप किसी अपवाद की परवाह नहीं करते हैं, जिसकी आपको उम्मीद नहीं थी, तो आप किसी को कॉल स्टैक विल की शर्त लगाते हैं और इसके हैंडलर तक पहुंचने से पहले अपवाद को मारना तोड़फोड़ होगा।

"लेकिन ... लेकिन ... फिर उन अन्य अपवादों में से एक जिनकी मुझे परवाह नहीं है, मेरे कार्य को विफल करने का कारण बन सकते हैं!"

हाँ। लेकिन वे हमेशा अधिक महत्वपूर्ण होंगे तो स्थानीय स्तर पर उन्हें संभालना होगा। जैसे फायर अलार्म या बॉस आपको बता रहा है कि आप जो कर रहे हैं उसे रोकें और एक और जरूरी काम करें जो पॉप अप हो।


-3

आपको हर प्रक्रिया के शीर्ष स्तर पर सामान्य अपवादों को पकड़ना चाहिए, और बग की रिपोर्ट करके और फिर प्रक्रिया को समाप्त करके इसे संभालना चाहिए।

आपको सामान्य अपवादों को नहीं पकड़ना चाहिए और निष्पादन को जारी रखने का प्रयास करना चाहिए।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.