अपवाद से निपटने के लिए ट्राई कैच का उपयोग करना सबसे अच्छा अभ्यास है


201

अपने सहकर्मी के कोड को किसी ऐसे व्यक्ति से बनाए रखने के लिए जो किसी वरिष्ठ डेवलपर होने का दावा करता है, मैं अक्सर निम्नलिखित कोड देखता हूं:

try
{
  //do something
}
catch
{
  //Do nothing
}

या कभी-कभी वे निम्न try catchब्लॉक जैसी फ़ाइलों को लॉग करने के लिए लॉगिंग जानकारी लिखते हैं

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);
}

मैं बस सोच रहा हूँ कि क्या उन्होंने किया है सबसे अच्छा अभ्यास है? यह मुझे भ्रमित करता है क्योंकि मेरी सोच में उपयोगकर्ताओं को पता होना चाहिए कि सिस्टम के साथ क्या होता है।

कृप्या मुझे कुछ सलाह दीजिए।


128
स्निपेट # 1 अस्वीकार्य समय का 99.999% है।
लेपी

22
उपयोगकर्ता को सीधे अपवाद प्रदर्शित करना कभी भी मुख्य रूप से दो कारणों से एक अच्छा विचार नहीं है: 1. यदि यह सामान्य उपयोगकर्ता है तो वह पढ़ने में त्रुटि संदेश से नाराज हो जाएगा, जो उसके लिए बहुत कम बताता है। 2. यदि वह है, तो तथाकथित हैकर (है), वह उपयोगी जानकारी प्राप्त कर सकता है। सबसे अच्छा अभ्यास, आईएमओ, अपवाद लॉग इन करना और मैत्रीपूर्ण त्रुटि संदेश दिखाना है।
लैरी

4
@leppie यदि कुछ अनपेक्षित होता है (जैसे NullReferenceया ArgumentNullवह एप्लिकेशन प्रवाह का हिस्सा नहीं है) तो इसका मतलब है कि एक बग है जिसे ठीक करने की आवश्यकता है ताकि उन्हें लॉग करने से आपके कोड को बहुत तेज़ी से डीबग करने में मदद मिलेगी।
लैरी

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

12
@Toan, ठीक है, अगर यह एक बैच की नौकरी है, तो मैं लॉग करने के लिए शीर्ष स्तर (मुख्य) पर पकड़ रहा हूं , और फिर एक अलार्म सेट करने के लिए रीथ्रोइंग करता हूं कि नौकरी असामान्य रूप से समाप्त हो गई। यदि यह एक वेब ऐप है, तो मैं एक वैश्विक हैंडलर को अपवाद बबल दे रहा हूं, लॉगिंग कर रहा हूं, और फिर उपयोगकर्ता को एक त्रुटि स्क्रीन पर पुनर्निर्देशित कर रहा हूं। आपके उपयोग की स्थिति परिदृश्य तय करती है कि आप उस अपवाद के साथ क्या करते हैं जब आप लॉग इन करते हैं या अन्यथा इसे संभालते हैं।
एंथनी पेग्राम

जवाबों:


300

मेरी अपवाद हैंडलिंग रणनीति है:

  • हुक करने के लिए सभी अखंडित अपवादों को पकड़ने के लिए Application.ThreadException event, फिर निर्णय लें:

    • UI एप्लिकेशन के लिए: इसे उपयोगकर्ता को माफी संदेश (winforms) के साथ पॉप करने के लिए
    • सेवा या कंसोल एप्लिकेशन के लिए: इसे किसी फ़ाइल (सेवा या कंसोल) में लॉग इन करें

फिर मैं हमेशा कोड के हर टुकड़े को जोड़ता हूं जो बाहरी रूप से चलाया जाता है try/catch:

  • Winforms बुनियादी ढांचे (लोड, क्लिक करें, चयनित परिवर्तन ...) द्वारा फायर किए गए सभी ईवेंट
  • सभी घटनाओं को तीसरे पक्ष के घटकों द्वारा निकाल दिया गया

फिर मैंने 'कोशिश / पकड़' में संलग्न किया

  • सभी ऑपरेशन जो मुझे पता है कि हर समय काम नहीं कर सकते हैं (आईओ संचालन, एक संभावित शून्य विभाजन के साथ गणना ...)। ऐसे मामले में, मैं ApplicationException("custom message", innerException)वास्तव में क्या हुआ का ट्रैक रखने के लिए एक नया फेंक देता हूं

इसके अतिरिक्त, मैं अपवादों को सही ढंग से क्रमबद्ध करने की पूरी कोशिश करता हूं । इसके कुछ अपवाद हैं:

  • उपयोगकर्ता को तुरंत दिखाए जाने की आवश्यकता है
  • चीजों को एक साथ रखने के लिए कुछ अतिरिक्त प्रसंस्करण की आवश्यकता होती है जब वे कैस्केडिंग की समस्याओं से बचने के लिए होते हैं (जैसे: एक पुट के finallyदौरान खंड में रखें। TreeView)
  • उपयोगकर्ता परवाह नहीं करता है, लेकिन यह जानना महत्वपूर्ण है कि क्या हुआ। इसलिए मैं हमेशा उन्हें लॉग करता हूं:

    • इवेंट लॉग में
    • या डिस्क पर एक .log फ़ाइल में

एप्लिकेशन टॉप लेवल एरर हैंडलर में अपवादों को संभालने के लिए कुछ स्थिर तरीकों को डिजाइन करना एक अच्छा अभ्यास है ।

मैं भी अपने आप को मजबूर करने की कोशिश करता हूं:

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

तो अंत में:

खराब:

// DON'T DO THIS, ITS BAD
try
{
    ...
}
catch 
{
   // only air...
}

निकम्मा:

// DONT'T DO THIS, ITS USELESS
try
{
    ...
}
catch(Exception ex)
{
    throw ex;
}

एक पकड़ने के बिना अंत में एक कोशिश पूरी तरह से मान्य है:

try
{
    listView1.BeginUpdate();

    // If an exception occurs in the following code, then the finally will be executed
    // and the exception will be thrown
    ...
}
finally
{
    // I WANT THIS CODE TO RUN EVENTUALLY REGARDLESS AN EXCEPTION OCCURED OR NOT
    listView1.EndUpdate();
}

मैं शीर्ष स्तर पर क्या करता हूं:

// i.e When the user clicks on a button
try
{
    ...
}
catch(Exception ex)
{
    ex.Log(); // Log exception

    -- OR --

    ex.Log().Display(); // Log exception, then show it to the user with apologies...
}

कुछ तथाकथित कार्यों में मैं क्या करता हूं:

// Calculation module
try
{
    ...
}
catch(Exception ex)
{
    // Add useful information to the exception
    throw new ApplicationException("Something wrong happened in the calculation module :", ex);
}

// IO module
try
{
    ...
}
catch(Exception ex)
{
    throw new ApplicationException(string.Format("I cannot write the file {0} to {1}", fileName, directoryName), ex);
}

अपवाद से निपटने के लिए बहुत कुछ है (कस्टम अपवाद) लेकिन नियम जो मैं ध्यान में रखने की कोशिश करता हूं वह उन सरल अनुप्रयोगों के लिए पर्याप्त हैं जो मैं करता हूं।

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

// Usage:

try
{
    // boom
}
catch(Exception ex)
{
    // Only log exception
    ex.Log();

    -- OR --

    // Only display exception
    ex.Display();

    -- OR --

    // Log, then display exception
    ex.Log().Display();

    -- OR --

    // Add some user-friendly message to an exception
    new ApplicationException("Unable to calculate !", ex).Log().Display();
}

// Extension methods

internal static Exception Log(this Exception ex)
{
    File.AppendAllText("CaughtExceptions" + DateTime.Now.ToString("yyyy-MM-dd") + ".log", DateTime.Now.ToString("HH:mm:ss") + ": " + ex.Message + "\n" + ex.ToString() + "\n");
    return ex;
}

internal static Exception Display(this Exception ex, string msg = null, MessageBoxImage img = MessageBoxImage.Error)
{
    MessageBox.Show(msg ?? ex.Message, "", MessageBoxButton.OK, img);
    return ex;
}

98
catch(Exception ex) { throw ex; }C # में बेमानी से भी बदतर है (अपवाद के प्रकार जो आप पकड़ रहे हैं)। पुनः प्रयोग करने के लिए, का उपयोग करें throw;। पूर्व के साथ, अपवाद ऐसा लगेगा जैसे यह आपके पहले से उत्पन्न हुआ था throw exजबकि बाद वाले के साथ, यह मूल throwकथन से ठीक से उत्पन्न होगा ।
बजे एक CVn

2
आप Application.ThreadExceptionईवेंट को हुक क्यों करते हैं और ए के साथ हर अपवाद को लपेटते हैं catch(Exception ex) {ex.Log(ex);}। मैं शायद इस बात से सहमत हूं कि पूर्व एक उत्कृष्ट अभ्यास है, लेकिन बाद वाला आपकी त्रुटि लॉग को डुप्लिकेट करने के जोखिम को जोड़ता है और छिपाता है कि अपवाद हुआ। साथ throw exही बहुत खराब है।
कीथ

1
मैं कैच के बारे में समझ गया (अपवाद पूर्व) {थ्रो एक्स; } बेकार होना। तो मुझे लगता है कि "निरर्थक" राज्य का सबसे अच्छा शब्द नहीं है "यह मत करो"। इसीलिए मैंने पोस्ट को थोड़ा और बेहतर तरीके से बदल दिया कि ट्राई कैच के दो पहले उदाहरण से बचना होगा।
लैरी

3
महान और रचनात्मक जवाब, सबसे अधिक मुझे केवल वाक्यांश का आनंद मिला हवा :) और इस Application.ThreadExceptionघटना के लिए धन्यवाद , मुझे इसके बारे में पता नहीं था, बहुत उपयोगी।
महदी तहसीलदार


61

सबसे अच्छा अभ्यास यह है कि अपवाद हैंडलिंग को कभी भी मुद्दों को छिपाना नहीं चाहिए । इसका मतलब है कि try-catchब्लॉक बेहद दुर्लभ होने चाहिए।

वहाँ 3 परिस्थितियों में एक try-catchसमझदारी का उपयोग कर रहे हैं ।

  1. हमेशा कम-डाउन के रूप में ज्ञात अपवादों से निपटें । हालाँकि, यदि आप एक अपवाद की अपेक्षा कर रहे हैं, तो आमतौर पर इसके लिए परीक्षण करना बेहतर अभ्यास है। उदाहरण के लिए पार्स, फॉर्मेटिंग और अंकगणितीय अपवाद लगभग हमेशा एक विशेष के बजाय तर्क की जाँच से बेहतर होते हैं try-catch

  2. यदि आपको अपवाद पर कुछ करने की आवश्यकता है (उदाहरण के लिए लॉगिंग या किसी लेन-देन को वापस करना) तो अपवाद को फिर से फेंक दें।

  3. हमेशा अज्ञात अपवादों से निपटें जैसा कि आप कर सकते हैं - एकमात्र कोड जो एक अपवाद का उपभोग करना चाहिए और फिर से नहीं फेंकना चाहिए वह UI या सार्वजनिक एपीआई होना चाहिए।

मान लीजिए कि आप एक दूरस्थ एपीआई से जुड़ रहे हैं, यहाँ आप कुछ त्रुटियों की उम्मीद करना जानते हैं (और उन परिस्थितियों में चीजें हैं), तो यह मामला है: 1

try 
{
    remoteApi.Connect()
}
catch(ApiConnectionSecurityException ex) 
{
    // User's security details have expired
    return false;
}

return true;

ध्यान दें कि कोई अन्य अपवाद नहीं पकड़ा गया है, क्योंकि वे अपेक्षित नहीं हैं।

अब मान लीजिए कि आप डेटाबेस में कुछ सहेजने की कोशिश कर रहे हैं। यदि यह विफल रहता है, तो हमें इसे वापस रोल करना होगा, इसलिए हमारे पास मामला 2 है:

try
{
    DBConnection.Save();
}
catch
{
    // Roll back the DB changes so they aren't corrupted on ANY exception
    DBConnection.Rollback();

    // Re-throw the exception, it's critical that the user knows that it failed to save
    throw;
}

ध्यान दें कि हम अपवाद को फिर से फेंक देते हैं - कोड उच्चतर अभी भी यह जानने की जरूरत है कि कुछ विफल हो गया है।

अंत में हमारे पास यूआई है - यहां हम पूरी तरह से अपवाद नहीं छोड़ना चाहते हैं, लेकिन हम उन्हें छिपाना नहीं चाहते हैं। यहाँ हमारे पास 3 का उदाहरण है:

try
{
    // Do something
}
catch(Exception ex) 
{
    // Log exception for developers
    WriteException2LogFile(ex);

    // Display message to users
    DisplayWarningBox("An error has occurred, please contact support!");
}

हालाँकि, अधिकांश API या UI फ्रेमवर्क में केस करने के सामान्य तरीके होते हैं। उदाहरण के लिए ASP.Net में एक पीले रंग की त्रुटि स्क्रीन होती है जो अपवाद विवरणों को पूरा करती है, लेकिन इसे उत्पादन वातावरण में अधिक सामान्य संदेश के साथ बदला जा सकता है। उन लोगों का पालन करना सबसे अच्छा अभ्यास है क्योंकि यह आपको बहुत सारे कोड बचाता है, लेकिन यह भी क्योंकि त्रुटि लॉगिंग और प्रदर्शन हार्ड-कोडेड के बजाय कॉन्फ़िगर निर्णय होना चाहिए।

यह सभी का अर्थ है कि केस 1 (ज्ञात अपवाद) और केस 3 (एक-बंद यूआई हैंडलिंग) दोनों में बेहतर पैटर्न हैं (यूआई से निपटने में अपेक्षित त्रुटि या हाथ से बचने से बचें)।

यहां तक ​​कि केस 2 को बेहतर पैटर्न द्वारा प्रतिस्थापित किया जा सकता है, उदाहरण के लिए लेन-देन के क्षेत्र ( usingब्लॉक के दौरान किसी भी लेनदेन को रोलबैक नहीं किया गया है) डेवलपर्स के लिए सर्वोत्तम अभ्यास पैटर्न को गलत करना कठिन बना देता है।

उदाहरण के लिए मान लीजिए कि आपके पास बड़े पैमाने पर ASP.Net अनुप्रयोग है। त्रुटि लॉगिंग ELMAH के माध्यम से हो सकती है , त्रुटि प्रदर्शन स्थानीय रूप से एक सूचनात्मक YSoD और उत्पादन में एक अच्छा स्थानीयकृत संदेश हो सकता है। डेटाबेस कनेक्शन सभी लेन-देन स्कोप और usingब्लॉक के माध्यम से हो सकते हैं। आपको एक try-catchब्लॉक की आवश्यकता नहीं है ।

टीएल; डीआर: बेस्ट प्रैक्टिस वास्तव में try-catchब्लॉक का उपयोग नहीं करना है ।


4
@Jorj आपको पूरी पोस्ट पढ़नी चाहिए, और यदि आप अभी भी असहमत हैं, तो शायद यह अधिक रचनात्मक होगा कि मेरे समर्थन में से किसी एक तर्क के बजाय केवल यह बताएं कि आपको मेरा निष्कर्ष पसंद नहीं है। लगभग हमेशा एक बेहतर पैटर्न होता है try-catch- यह (कभी-कभी) उपयोगी हो सकता है और मैं यह तर्क नहीं दे रहा हूं कि आपको कभी भी उनका उपयोग नहीं करना चाहिए, लेकिन 99% समय एक बेहतर तरीका है।
कीथ

अब तक का सबसे अच्छा जवाब - लगभग हर .net विकास प्रकार में कुछ प्रकार का एक हैन्डलर होता है जो वैश्विक स्तर पर अपवादों से निपटने के लिए बहुत बेहतर होता है, जिससे उन्हें संभालना बहुत आसान हो जाता है और साथ ही साथ उन्हें आसानी से उड़ाना भी आसान हो जाता है। विकास में (कोई भी स्टैक ट्रेस के लिए लॉग फ़ाइल को खोदना क्यों चाहेगा?) @Kieth, मैं आपके TLDR के साथ नेतृत्व करूंगा, और वैश्विक हैंडलर (यानी थ्रेडएक्ससेप्शन, Application_Error, आदि) के कुछ उदाहरणों में जोड़ दूंगा। हर तरह से विशेष त्रुटियों को
पकड़ें

34

एक अपवाद एक अवरुद्ध त्रुटि है

सबसे पहले, सबसे अच्छा अभ्यास किसी भी तरह की त्रुटि के लिए अपवाद नहीं फेंकना चाहिए , जब तक कि यह एक अवरुद्ध त्रुटि न हो

यदि त्रुटि अवरुद्ध है , तो अपवाद को फेंक दें। एक बार अपवाद पहले ही फेंक दिए जाने के बाद, इसे छिपाने की कोई आवश्यकता नहीं है क्योंकि यह असाधारण है; उपयोगकर्ता को इसके बारे में बताएं (आपको UI में उपयोगकर्ता के लिए उपयोगी कुछ के लिए पूरे अपवाद को पुन: स्वरूपित करना चाहिए)।

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

उदाहरण के लिए, यदि आप जानते हैं कि कुछ पूर्णांक इनपुट अमान्य प्रारूप के साथ आ सकते हैं, int.TryParseइसके बजाय उपयोग करें int.Parse। बहुत सारे मामले हैं जहां आप यह कहने के बजाय ऐसा कर सकते हैं "यदि यह विफल रहता है, तो बस एक अपवाद फेंक दें"।

अपवाद फेंकना महंगा है।

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

  • ASP.NET: Global.asax Application_Error
  • अन्य: AppDomain.FirstChanceException घटना

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

बाकी मामलों के लिए:

  • अपवादों से बचने की कोशिश करें।
  • यदि यह संभव नहीं है: पहला मौका अपवाद हैंडलर।
  • या एक PostSharp पहलू (AOP) का उपयोग करें।

कुछ कमेंट पर @thewhiteambit का जवाब ...

@ वेधशाला ने कहा:

अपवाद घातक-त्रुटियां नहीं हैं, वे अपवाद हैं! कभी-कभी वे एरर भी नहीं होते हैं, लेकिन उन पर विचार करने के लिए फेटल-एरर्स पूरी तरह से झूठी समझ है कि अपवाद क्या हैं।

सबसे पहले, कैसे एक अपवाद भी एक त्रुटि नहीं हो सकती है?

  • कोई डेटाबेस कनेक्शन => अपवाद नहीं।
  • कुछ प्रकार => अपवाद के लिए पार्स करने के लिए अमान्य स्ट्रिंग प्रारूप
  • JSON को पार्स करने की कोशिश करना और जबकि इनपुट वास्तव में JSON => अपवाद नहीं है
  • तर्क, nullजबकि वस्तु अपेक्षित थी => अपवाद
  • कुछ पुस्तकालय में एक बग => एक अप्रत्याशित अपवाद फेंकता है
  • एक सॉकेट कनेक्शन है और यह डिस्कनेक्ट हो जाता है। फिर आप एक संदेश भेजने का प्रयास करते हैं => अपवाद
  • ...

हम 1k मामलों को सूचीबद्ध कर सकते हैं जब एक अपवाद फेंक दिया जाता है, और आखिरकार, संभावित मामलों में से कोई भी एक त्रुटि होगी ।

एक अपवाद है , एक त्रुटि क्योंकि दिन के अंत में यह एक वस्तु जो नैदानिक जानकारी एकत्र करता है - यह एक संदेश है और यह तब होता है जब कुछ गलत हो जाता।

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

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

[...] उन पर विचार करें कि घातक-त्रुटियां पूरी तरह से गलत हैं कि अपवाद क्या हैं।

आमतौर पर अपवादों में कुछ ऑपरेशन प्रवाह में कटौती होती है और उन्हें मानव-समझने योग्य त्रुटियों में बदलने के लिए नियंत्रित किया जाता है। इस प्रकार, यह एक अपवाद की तरह लगता है कि वास्तव में त्रुटि मामलों को संभालने और एक आवेदन / सेवा पूर्ण दुर्घटना से बचने और उपयोगकर्ता / उपभोक्ता को सूचित करने के लिए उन पर काम करने के लिए एक बेहतर प्रतिमान है कि कुछ गलत हुआ।

@Thewhiteambit चिंताओं के बारे में अधिक जवाब

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

  1. यदि आपका ऐप डेटाबेस में डेटा को बनाए रखने के बिना ऑफ़लाइन काम कर सकता है, तो आपको अपवादों का उपयोग नहीं करना चाहिए , क्योंकि नियंत्रण प्रवाह को लागू करने का उपयोग try/catchएक विरोधी पैटर्न के रूप में माना जाता है। ऑफ़लाइन कार्य संभव उपयोग का मामला है, इसलिए आप यह जानने के लिए नियंत्रण प्रवाह को लागू करते हैं कि डेटाबेस सुलभ है या नहीं, आप तब तक प्रतीक्षा नहीं करते जब तक कि यह अनुपलब्ध न हो

  2. पार्स बात भी एक उम्मीद मामले (है असाधारण नहीं मामला )। यदि आप यह उम्मीद करते हैं, तो आप नियंत्रण प्रवाह करने के लिए अपवादों का उपयोग नहीं करते हैं! । आपको यह जानने के लिए उपयोगकर्ता से कुछ मेटाडेटा मिलता है कि उसकी संस्कृति क्या है और आप इसके लिए फॉर्मेटर्स का उपयोग करते हैं! .NET इस और अन्य वातावरणों का भी समर्थन करता है, और एक अपवाद क्योंकि नंबर स्वरूपण से बचना चाहिए यदि आप अपने एप्लिकेशन / सेवा के संस्कृति-विशिष्ट उपयोग की अपेक्षा करते हैं

एक अखंडित अपवाद आमतौर पर एक त्रुटि बन जाता है, लेकिन अपवाद स्वयं कोडप्रोजेक्ट नहीं होते हैं। विज्ञापन / विज्ञापन / 15921/Not-All-Exception-Are-Errors

यह लेख केवल एक राय है या लेखक का दृष्टिकोण है।

चूँकि विकिपीडिया पर केवल लेखिका की राय हो सकती है, इसलिए मैं यह नहीं कहूंगा कि यह हठधर्मिता है , लेकिन जाँच करें कि अपवाद लेख द्वारा कोडिंग कहीं किसी पैराग्राफ में क्या कहता है:

[...] प्रोग्राम को जारी रखने के लिए उत्पन्न होने वाली विशिष्ट त्रुटियों को संभालने के लिए इन अपवादों का उपयोग करना अपवाद द्वारा कोडिंग कहा जाता है। यह विरोधी पैटर्न प्रदर्शन और रखरखाव में सॉफ़्टवेयर को जल्दी से ख़राब कर सकता है।

यह भी कहीं कहता है:

गलत अपवाद उपयोग

अक्सर अपवाद द्वारा कोडिंग सॉफ्टवेयर में गलत अपवाद उपयोग के साथ आगे के मुद्दों को जन्म दे सकती है। एक अद्वितीय समस्या के लिए अपवाद हैंडलिंग का उपयोग करने के अलावा, गलत अपवाद उपयोग अपवाद को उठाने के बाद भी कोड निष्पादित करके इसे आगे ले जाता है। यह खराब प्रोग्रामिंग विधि कई सॉफ्टवेयर भाषाओं में गोटो विधि से मिलती जुलती है, लेकिन सॉफ्टवेयर में समस्या का पता लगने के बाद ही होती है।

ईमानदारी से, मेरा मानना ​​है कि सॉफ़्टवेयर को विकसित नहीं किया जा सकता है और उपयोग के मामलों को गंभीरता से नहीं लेना चाहिए। अगर आपको पता है कि ...

  • आपका डेटाबेस ऑफ़लाइन हो सकता है ...
  • कुछ फ़ाइल लॉक की जा सकती हैं ...
  • कुछ स्वरूपण का समर्थन नहीं किया जा सकता है ...
  • कुछ डोमेन सत्यापन विफल हो सकते हैं ...
  • आपका एप्लिकेशन ऑफ़लाइन मोड में काम करना चाहिए ...
  • जो भी उपयोग मामला ...

... आप इसके लिए अपवादों का उपयोग नहीं करेंगे । आप नियमित नियंत्रण प्रवाह का उपयोग करके इन मामलों का समर्थन करेंगे ।

और अगर कुछ अनपेक्षित उपयोग के मामले को कवर नहीं किया गया है, तो आपका कोड तेजी से विफल हो जाएगा, क्योंकि यह एक अपवाद फेंक देगा । सही है, क्योंकि एक अपवाद एक असाधारण मामला है

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


6

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

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

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


6

मुझे पता है कि यह एक पुराना प्रश्न है, लेकिन यहां किसी ने भी MSDN लेख का उल्लेख नहीं किया है, और यह दस्तावेज था जिसने वास्तव में मेरे लिए इसे मंजूरी दे दी थी, MSDN के पास इस पर एक बहुत अच्छा दस्तावेज है, आपको निम्नलिखित शर्तों के सत्य होने पर अपवादों को पकड़ना चाहिए:

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

  • आप एक नया, अधिक विशिष्ट अपवाद बना और फेंक सकते हैं।

int GetInt(int[] array, int index)
{
    try
    {
        return array[index];
    }
    catch(System.IndexOutOfRangeException e)
    {
        throw new System.ArgumentOutOfRangeException(
            "Parameter index is out of range.");
    }
}
  • आप अतिरिक्त हैंडलिंग के लिए इसे पारित करने से पहले एक अपवाद को आंशिक रूप से संभालना चाहते हैं। निम्न उदाहरण में, कैच ब्लॉक का उपयोग अपवाद को फिर से फेंकने से पहले एक त्रुटि लॉग में प्रविष्टि जोड़ने के लिए किया जाता है।
    try
{
    // Try to access a resource.
}
catch (System.UnauthorizedAccessException e)
{
    // Call a custom error logging procedure.
    LogError(e);
    // Re-throw the error.
    throw;     
}

मेरा सुझाव है कि संपूर्ण " अपवाद और अपवाद हैंडलिंग " अनुभाग और अपवाद के लिए सर्वोत्तम अभ्यास भी पढ़ें ।


1

बेहतर दृष्टिकोण दूसरा है (वह जिसमें आप अपवाद प्रकार निर्दिष्ट करते हैं)। इसका लाभ यह है कि आप जानते हैं कि आपके कोड में इस प्रकार का अपवाद हो सकता है। आप इस प्रकार के अपवाद को संभाल रहे हैं और आप फिर से शुरू कर सकते हैं। यदि कोई अन्य अपवाद आया है, तो इसका मतलब है कि कुछ गलत है जो आपको अपने कोड में बग ढूंढने में मदद करेगा। आवेदन अंततः दुर्घटनाग्रस्त हो जाएगा, लेकिन आपको पता चल जाएगा कि आपके द्वारा याद किया गया कुछ है (बग) जिसे ठीक करने की आवश्यकता है।


1

अपवाद के साथ, मैं निम्नलिखित प्रयास करता हूं:

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

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

कोड में, कुछ इस तरह से:

try{
    //Some code here
}
catch(DivideByZeroException dz){
    AlerUserDivideByZerohappened();
}
catch(Exception e){
    treatGeneralException(e);
}
finally{
    //if a IO operation here i close the hanging handlers for example
}

1
शून्य अपवादों को विभाजित करें और जैसे कि किसी 0अंश के लिए पहले से जाँचने से बेहतर है , बजाय एक try-catch। इसके अलावा Exceptionयहां जेनेरिक को क्यों पकड़ा जाए ? आप उन सभी मामलों में जहां आप इसकी उम्मीद नहीं कर रहे हैं, से निपटने में त्रुटि बुलबुले को छोड़ देने से बेहतर है।
कीथ

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

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

मैं यह पता लगाने की कोशिश कर रहा हूं कि क्या वास्तव में लोगों को "गोटो" के लिए एक और पर्यायवाची जोड़ने के लिए प्रेरित कर रहा है। लेकिन शून्य से विभाजन के संबंध में, यह एक प्रकार का अपवाद होगा जो मैं देख सकता हूं कि भाषा वृद्धि को सही ठहराता है। क्यों? क्योंकि यह अच्छी तरह से हो सकता है कि ए) शून्य सांख्यिकीय रूप से आपके डेटा सेट में एक infinitesimal है, और B) अपवाद का उपयोग करना (अनुमति देना) अधिक कुशल हो सकता है, क्योंकि विभाजन करना एक शून्य विभाजक के लिए परीक्षण करने का एक तरीका है। जब A और B सही होते हैं, तो अपवाद का उपयोग करके आपके प्रोग्राम का औसत निष्पादन तेजी से होगा, और यह छोटा भी हो सकता है।
माइक लेटन

1

दूसरा दृष्टिकोण एक अच्छा है।

यदि आप त्रुटि नहीं दिखाना चाहते हैं और रनटाइम अपवाद (यानी त्रुटि) को दिखाते हुए आवेदन के उपयोगकर्ता को भ्रमित करते हैं जो उनसे संबंधित नहीं है, तो बस त्रुटि लॉग करें और तकनीकी टीम इस मुद्दे को देख सकती है और इसे हल कर सकती है।

try
{
  //do some work
}
catch(Exception exception)
{
   WriteException2LogFile(exception);//it will write the or log the error in a text file
}

मेरा सुझाव है कि आप अपने पूरे आवेदन के लिए दूसरे दृष्टिकोण के लिए जाएं।


2
दूसरा दृष्टिकोण उपयोगकर्ता को यह नहीं दिखाता है कि त्रुटि हुई है - उदाहरण के लिए यदि वे कुछ बचत कर रहे थे तो उन्हें पता नहीं होगा कि यह विफल हो गया है। catchब्लॉक को हमेशाthrow अपवाद को बुलाने के लिए कॉल करना चाहिए या कुछ वापस करना चाहिए / ऐसा कुछ दिखाना चाहिए जो उपयोगकर्ता को बताए कि कार्रवाई विफल हो गई है। आप समर्थन कॉल प्राप्त करना चाहते हैं जब वे जो कुछ भी है उसे बचाने में विफल रहते हैं, न कि 6 महीने बाद जब वे इसे पुनर्प्राप्त करने का प्रयास करते हैं और इसे नहीं पा सकते हैं।
कीथ

0

खाली कैच ब्लॉक छोड़ना सबसे बुरा काम है। यदि कोई त्रुटि है तो उसे संभालने का सबसे अच्छा तरीका है:

  1. इसे फ़ाइल \ डेटाबेस आदि में लॉग इन करें।
  2. इसे मक्खी पर ठीक करने की कोशिश करें (हो सकता है उस ऑपरेशन को करने का वैकल्पिक तरीका आजमा रहे हों)
  3. यदि हम इसे ठीक नहीं कर सकते हैं, तो उपयोगकर्ता को सूचित करें कि कुछ त्रुटि है और निश्चित रूप से ऑपरेशन को निरस्त करें

0

मेरे लिए, अपवाद को संभालना व्यापार नियम के रूप में देखा जा सकता है। जाहिर है, पहला दृष्टिकोण अस्वीकार्य है। दूसरा एक बेहतर है और यदि संदर्भ ऐसा कहता है तो यह 100% सही तरीका हो सकता है। अब, उदाहरण के लिए, आप एक Outlook Addin विकसित कर रहे हैं। यदि आप जोड़-तोड़ न किए गए अपवाद को फेंक देते हैं, तो हो सकता है कि आउटलुक उपयोगकर्ता अब यह जान सके क्योंकि आउटलुक विफल होने के कारण आउटलुक खुद को नष्ट नहीं करेगा। और आपके पास यह जानने के लिए कठिन समय है कि क्या गलत हुआ। इसलिए, इस मामले में दूसरा दृष्टिकोण, मेरे लिए, यह एक सही है। अपवाद को लॉग करने के अलावा, आप उपयोगकर्ता को त्रुटि संदेश प्रदर्शित करने का निर्णय ले सकते हैं - मैं इसे व्यावसायिक नियम मानता हूं।


0

त्रुटि होने पर एक अपवाद को फेंकने के लिए सबसे अच्छा अभ्यास है। क्योंकि एक त्रुटि हुई है और इसे छिपाया नहीं जाना चाहिए।

लेकिन वास्तविक जीवन में जब आप इसे छुपाना चाहते हैं तो आपके सामने कई परिस्थितियाँ आ सकती हैं

  1. आप तीसरे पक्ष के घटक पर भरोसा करते हैं और आप त्रुटि के मामले में कार्यक्रम जारी रखना चाहते हैं।
  2. आपके पास एक व्यावसायिक मामला है जिसे आपको त्रुटि के मामले में जारी रखने की आवश्यकता है

6
सं करो नहीं फेंक Exceptionकभी। Exceptionआप जो चाहते हैं, उसका एक उपयुक्त उपवर्ग फेंक दें , लेकिन कभी नहीं Exceptionक्योंकि यह बिल्कुल अर्थ संबंधी जानकारी नहीं देता है। मैं बाहर एक फ्लैट नहीं देख सकता, जहां यह फेंकने के लिए समझ में आता है, Exceptionलेकिन एक उपवर्ग नहीं।
बजे एक CVn


0

catchकिसी भी तर्क के बिना बस है खाने अपवाद और किसी काम का नहीं है। यदि कोई घातक त्रुटि होती है तो क्या होगा? यह जानने का कोई तरीका नहीं है कि यदि आप तर्क के बिना कैच का उपयोग करते हैं तो क्या हुआ।

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


catch(Exception)अंत में एक जनरल क्यों है ? यदि आप इसकी उम्मीद नहीं कर रहे हैं, तो अगली परत तक इसे पारित करने के लिए हमेशा सबसे अच्छा अभ्यास है।
कीथ

1
@ हाँ, आप सही हैं ... अपवादों को पकड़ने का कोई मतलब नहीं है, जिसकी आप उम्मीद नहीं कर रहे हैं, लेकिन आप लॉगिंग उद्देश्य के लिए सामान्य अपवाद कर सकते हैं ..
अनिरुद्ध

0

कभी-कभी आपको अपवादों का इलाज करने की आवश्यकता होती है जो उपयोगकर्ताओं को कुछ नहीं कहते हैं।

मेरा तरीका है:

  • महत्वपूर्ण अपवादों के लिए आवेदन के स्तर (अर्थात वैश्विक रूप में।) पर बिना किसी अपवाद के पकड़ने के लिए (आवेदन उपयोगी नहीं हो सकता है)। इन बातों को मैं जगह पर नहीं पकड़ रहा हूं। बस उन्हें ऐप स्तर पर लॉग इन करें और सिस्टम को अपना काम करने दें।
  • "जगह पर" पकड़ो और उपयोगकर्ता को कुछ उपयोगी जानकारी दिखाएं (गलत संख्या दर्ज की गई, पार्स नहीं कर सकते)।
  • जगह पर पकड़ और "मैं पृष्ठभूमि पर अद्यतन जानकारी के लिए जाँच करेंगे, लेकिन सेवा नहीं चल रही है" जैसी सीमांत समस्याओं पर कुछ भी नहीं करें।

यह निश्चित रूप से सबसे अच्छा अभ्यास नहीं है। ;-)


0

तुम्हें बताने के लिए मेरे पास कुछ है:

स्निपेट # 1 स्वीकार्य नहीं है क्योंकि यह अपवाद की अनदेखी कर रहा है। (यह निगल रहा है जैसे कुछ भी नहीं हुआ)।

इसलिए कैच ब्लॉक को न जोड़ें जो कुछ भी नहीं करता है या केवल पुनर्विचार करता है।

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

सामान्य प्रवाह कार्यक्रम तर्क के लिए अपवाद का उपयोग न करें। उदाहरण के लिए:

उदाहरण इनपुट सत्यापन। <- यह मान्य असाधारण स्थिति नहीं है, बल्कि आपको यह IsValid(myInput);जांचने के लिए विधि लिखनी चाहिए कि इनपुट आइटम मान्य है या नहीं।

अपवाद से बचने के लिए डिज़ाइन कोड। उदाहरण के लिए:

int Parse(string input);

यदि हम ऐसे मान को पास कर लेते हैं जिन्हें int के लिए पार्स नहीं किया जा सकता है, तो यह विधि फेंक और अपवाद होगी, इसके बजाय हम इस तरह से कुछ लिख सकते हैं:

bool TryParse(string input,out int result); <- यह विधि बूलियन को संकेत देती है कि यदि पार्स सफल था।

हो सकता है कि यह इस सवाल के दायरे से थोड़ा बाहर हो, लेकिन मुझे उम्मीद है कि यह आपको सही निर्णय लेने में मदद करेगा जब इसके बारे में try {} catch(){}और अपवाद होंगे।

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