2010-02-22 14 views
18

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

उदा

catch (Exception ex) 
    { 
     transaction.VoidOrder(transactionID); 

     LogError(ex.ToString()); 
     Response.Redirect("Checkout", false); 
    } 

तो VoidOrder या यहाँ तक कि LogError तरीकों बाहर बम सकता है। अभी जब मैं VoidOrder पर कॉल करता हूं, तो मुझे transactionID पर एक शून्य रिफ मिलता है क्योंकि यह एक बीएल विधि कहता है और उस बीएल विधि में मैं फिर से फेंक रहा हूं ताकि मैं उपरोक्त कोड में इस उच्च स्तर पर इसे पकड़ सकूं। लेकिन अगर मैं एक पकड़ के अंदर फिर से फेंक रहा हूं तो मुझे उसे पकड़ने की जरूरत है।

यूआई/codebehind स्तर से आने वाली कॉल करने के लिए अन्य स्तरों एक कोशिश पकड़ है, जहां हम हमेशा एक कस्टम अपवाद को पकड़ने का उपयोग करें:

+0

उम्मीद है कि यह सिर्फ छद्म कोड है, लेकिन आपको शायद एक सामान्य अपवाद को पकड़ना नहीं चाहिए। –

+2

कैच-ऑल के रूप में एक सामान्य अपवाद को पकड़ना ठीक है, जब तक कि आपने पहले विशिष्ट अपवादों को पकड़ने की कोशिश की है (क्योंकि आप प्रति प्रयास कई कैच कर सकते हैं) ... ऊपर अकेले हां अधिक विशिष्ट होना चाहिए ... –

+0

इसके लायक होने के लिए, मैं पहले त्रुटि लॉग करूंगा। यदि Transaction.voidorder में कोई अपवाद है, तो आपके पास –

उत्तर

15

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

codebehind:

protected void btnSubmit_Click(object sender, EventArgs e) 
{ 
    //do something when a button is clicked... 
    try 
    { 
     MyBL.TakeAction() 
    } 
    catch(MyApplicationCustomException ex) 
    { 
     //display something to the user, etc. 
     ltlErrorPane.Text = ex.Message; 

     //or redirect if desired 
     if(ex.ErrorType == MyCustomErrorsType.Transactional) 
     { 
      Response.Redirect("~/Errors/Transaction.aspx"); 
     } 
    } 
} 

बीएल:

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

public class MyBL 
{ 
    public static void TakeAction() 
    { 
     try 
     { 
      //do something 
     } 
     catch(SpecificDotNetException ex) 
     { 
      //log, wrap and throw 
      MyExceptionManagement.LogException(ex) 
      throw new MyApplicationCustomException(ex, "Some friendly error message", MyCustomErrorsType.Transactional); 
     } 
     finally 
     { 
      //clean up... 
     } 
    } 
} 

अपवाद हैंडलर:

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

public static class MyExceptionManagement 
{ 
    public static bool LogException(Exception ex) 
    { 
     try 
     { 
      //try logging to a log source by priority, 
      //if it fails with all sources, return false as a last resort 
      //we choose not to let logging issues interfere with user experience 

      //if logging worked 
      return true; 
     } 
     catch(Exception ex) 
     { 
      //in most cases, using try-catch as a true-false is bad practice 
      //but when logging an exception causes an exception itself, we do 
      //use this as a well-considered choice. 
      return false; 
     } 
    } 
} 

अन्त में, एक असफल-सुरक्षित के रूप में, हम Application_Error वैश्विक ईवेंट हैंडलर (Global.asax में) लागू करते हैं। यह उन मामलों के लिए एक अंतिम उपाय है जहां हमने कुछ सही तरीके से प्रयास नहीं किया था। हम आम तौर पर एक दोस्ताना त्रुटि पृष्ठ पर लॉग इन और रीडायरेक्ट करते हैं। यदि उपर्युक्त कस्टम त्रुटि प्रबंधन सफलतापूर्वक किया जाता है, तो बहुत कम त्रुटियां इसे वैश्विक हैंडलर में लाएंगी।

उम्मीद है कि इससे थोड़ा सा मदद मिल सकती है। यह एक संभावित समाधान है। इसने कुछ बड़े अनुप्रयोगों पर कई वर्षों तक हमारे लिए बहुत अच्छा काम किया है ..

+0

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

+0

धन्यवाद नहीं है। उस मुद्दे पर स्पष्टता के लिए भी संपादित किया गया .. –

+0

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

0

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

+1

कॉल करता है मुझे वापस रोल करने की आवश्यकता नहीं है। मैं एसओएपी कॉल भेज रहा हूं। यदि कोई असफल रहता है, तो उपयोगकर्ता को चेकआउट पर वापस रीडायरेक्ट करें। – PositiveGuy

+0

क्षमा करें, मैं आपके VoidOrder को किसी प्रकार की रोल बैक के रूप में समझ गया, क्योंकि आपको स्मृति में कुछ लेनदेन डेटा से निपटना होगा। आपके मूल प्रश्न का उत्तर देते हुए, ऐसा लगता है कि आपको अपने बीएल में अधिक सुरक्षात्मक कोड डालना पड़ सकता है। जैसा कि आपने बताया, आज आपको एक नल रिफ अपवाद मिल रहा है, जिसे आपको पूरा करने की आवश्यकता हो सकती है। आप उस बिंदु पर पहुंच जाएंगे जहां आपको अपने आवेदन से केवल त्रुटियां मिलती हैं, वे वास्तविक अप्रत्याशित त्रुटियां हैं जिनसे आप पुनर्प्राप्त नहीं कर सकते हैं, और फिर मैं ऊपर सुझाए गए रेथ्रो पैटर्न का उपयोग करूंगा। –

5

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

वहाँ नेस्टेड ब्लॉक की संख्या में कटौती करने के लिए तरीके (उदाहरण के लिए, हैंडलिंग त्रुटि को मजबूत बनाने ASP.NET के HttpApplication.Error हैंडलर (उर्फ Application_Error) का उपयोग कर रहे हैं), लेकिन आप अपने को संभालने कोड से तैयार की किसी भी अपवाद को पकड़ने और एक बैकअप योजना को लागू करना चाहिए अगर सब कुछ विफल रहता है।

1

आपके घोंसले के मुद्दे का एक अन्य समाधान उन कार्यों में आंतरिक कार्यों (लॉगइरर इत्यादि) के लिए प्रयास/पकड़ तर्क को समाहित करना होगा, बजाय उन्हें पकड़ने के लिए कॉलर के आधार पर। LogError के लिए, यह समझ में आ जाएगा क्योंकि आप शायद एक टूटी हुई त्रुटि लॉगर को उसी तरह से संभालना चाहते हैं, कोई फर्क नहीं पड़ता कि कोई त्रुटि लॉग करने का प्रयास कर रहा है।

1

शायद एक प्रश्न है कि कोई समझ सकता है कि आप नेस्टेड प्रयास/कैच का उपयोग क्यों कर रहे हैं। कभी-कभी उनका उपयोग करने के लिए अपरिहार्य हो जाता है, लेकिन मैं आमतौर पर सुंदर नहीं कहता हूं।
आपको यह समझना चाहिए कि चिंताओं को अलग करना जरूरी है।

एक getControl विधि में एक स्क्रिप्ट डालना नहीं चाहिए, न ही सहेजने की विधि को सहेजने से अधिक करना चाहिए।

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

संबंधित मुद्दे