c# - मैं कैसे एक अनियंत्रित अपवाद से ठीक हो?




java design (6)

अनियंत्रित अपवाद ठीक हैं यदि आप हर विफलता को उसी प्रकार से संभाल करना चाहते हैं, उदाहरण के लिए इसे लॉग करके और अगले अनुरोध पर लंघन, उपयोगकर्ता को संदेश प्रदर्शित करने और अगली घटना को संभालने आदि। अगर यह मेरा उपयोग मामला है, तो मैं मेरे सिस्टम में उच्च स्तर पर कुछ सामान्य अपवाद प्रकार को करना है, और हर चीज को उसी तरीके से संभालना है।

लेकिन मैं विशिष्ट समस्याओं से पुनर्प्राप्त करना चाहता हूं, और मुझे यकीन नहीं है कि अनचाहे अपवादों के साथ संपर्क करने का सबसे अच्छा तरीका है। यहाँ एक ठोस उदाहरण है।

मान लीजिए मेरे पास एक वेब अनुप्रयोग है, जो स्ट्रट्स 2 और हाइबरनेट का उपयोग कर बनाया गया है। यदि कोई अपवाद बुलबुले मेरी "कार्रवाई" तक है, तो मैं इसे लॉग इन करता हूं, और उपयोगकर्ता के लिए एक बहुत माफी माँगता हूं। लेकिन मेरे वेब एप्लिकेशन के कार्यों में से एक नया उपयोगकर्ता खाता बना रहा है, जिसके लिए एक अद्वितीय उपयोगकर्ता नाम की आवश्यकता होती है। यदि कोई उपयोगकर्ता नाम पहले से मौजूद है, तो सीतनिद्रा में होना एक org.hibernate.exception.ConstraintViolationException (एक अनियंत्रित अपवाद) मेरे सिस्टम की हिम्मत में नीचे फेंकता है। मैं वाकई इस विशेष समस्या से पुनर्प्राप्त करना चाहूंगा कि उपयोगकर्ता को एक और उपयोगकर्ता नाम चुनने के बजाय, "हमने आपकी समस्या को लॉग ऑन किया है, लेकिन अब आप को रोक दिया" संदेश देने के लिए कहें।

यहां पर विचार करने के लिए कुछ बिंदु हैं:

  1. वहाँ बहुत सारे लोग खातों को एक साथ बनाते हैं मैं पूरी उपयोगकर्ता तालिका को "SELECT" के बीच लॉक नहीं करना चाहता, यह देखने के लिए कि क्या नाम मौजूद है और "INSERT" अगर ऐसा नहीं है। रिलेशनल डेटाबेस के मामले में, इस पर काम करने के लिए कुछ युक्तियां हो सकती हैं, लेकिन जो वास्तव में मुझे दिलचस्पी है, वह सामान्य मामला है, जहां एक अपवाद के लिए पूर्व जांच मौलिक दौड़ की स्थिति के कारण काम नहीं करेगी। फाइल सिस्टम पर फाइल देखने के लिए एक ही चीज़ लागू हो सकती है, आदि।
  2. "इंक।" में तकनीकी स्तंभों को पढ़कर प्रेरित सीआईटीओ की प्रवृत्ति को देखते हुए मुझे दृढ़ता तंत्र के चारों ओर indirection की एक परत की आवश्यकता है ताकि मैं सीतनिद्रा में प्रवेश कर सकता हूं और कोडो का इस्तेमाल कर सकता हूं या जो कुछ भी, दृढ़ता कोड की परत तथ्य की बात के रूप में, मेरे सिस्टम में अमूर्त की कई ऐसी परतें हैं मैं उन्हें अनियंत्रित अपवादों के बावजूद लीक से कैसे रोक सकता हूं?
  3. चेक अपवादों की नीचता की कमजोरियों में से एक को स्टैक पर प्रत्येक कॉल में "संभाल" करना होता है- या तो घोषित करते हुए कि कॉलिंग विधि उन्हें फेंकता है, या उन्हें पकड़कर और उन्हें संभालने के द्वारा। उन्हें संभालने का मतलब अक्सर उन्हें अमूर्त के स्तर के लिए उपयुक्त प्रकार के एक और जाँच अपवाद में लपेटने का मतलब है। उदाहरण के लिए, उदाहरण के लिए, चेक अपवाद भूमि में, मेरे यूज़ररायजिस्टेशन के एक फ़ाइल सिस्टम-आधारित कार्यान्वयन IOException को पकड़ सकता है, जबकि एक डेटाबेस कार्यान्वयन SQLException को पकड़ सकता है, लेकिन दोनों एक UserNotFoundException फेंक UserNotFoundException जो अंतर्निहित कार्यान्वयन को छुपाता है मैं अनियंत्रित अपवादों का लाभ कैसे उठा सकता हूं, अपने आप को प्रत्येक परत पर इस लपेटन के बोझ को दूर करने के लिए, कार्यान्वयन के विवरण को छूने के बिना?

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

try {
    throw new IllegalArgumentException();
} catch (Exception e) {
    System.out.println("boom");
}

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

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


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

मदद?


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

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


  1. प्रश्न वास्तव में चेक बनाम अनियंत्रित बहस से संबंधित नहीं है, यह दोनों अपवाद प्रकारों पर लागू होता है।

  2. उस बिंदु के बीच जहां constraintiolationException फेंक दिया जाता है और बिंदु, जहां हम एक अच्छा त्रुटि संदेश प्रदर्शित करके उल्लंघन को संभाल करना चाहते हैं, उस स्टैक पर बड़ी संख्या में कॉल की गई है जिसे तत्काल रोकना चाहिए और समस्या की परवाह नहीं करनी चाहिए। इससे अपवाद तंत्र को सही विकल्प के रूप में मूल्यों को वापस करने के लिए अपवाद से कोड को पुन: डिज़ाइन करने का विरोध किया जाता है।

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

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

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

    शीर्ष स्तर के हैंडलर के करीब कहीं, बस एक अलग तरीके से MessageException को संभालना इसके बजाय "हमने आपकी समस्या लॉग की है लेकिन अभी आप को रोक दिया गया है" बस संदेश एक्सपेस्टमेंट में निहित संदेश प्रदर्शित करें, कोई स्टैक ट्रेस नहीं

    संदेश एक्सपैशन कुछ अतिरिक्त कन्स्ट्रक्टर पैरामीटर ले सकता है, जैसे कि समस्या का विस्तृत स्पष्टीकरण, अगले क्रिया उपलब्ध (रद्द करें, एक अलग पृष्ठ पर जाएं), आइकन (त्रुटि, चेतावनी) ...

कोड ऐसा दिख सकता है

// insert the user
try {
   hibernateSession.save(user);
} catch (ConstraintViolationException e) {
   throw new MessageException("Username " + user.getName() + " already exists. Please choose a different name.");
}

एक पूरी तरह से अलग जगह में एक शीर्ष अपवाद हैंडलर है

try {
   ... render the page
} catch (MessageException e) {
   ... render a nice page with the message
} catch (Exception e) {
   ... render "we logged your problem but for now you're hosed" message
}

आईएमओ, रैपिंग अपवाद (चेक या अन्यथा) के कई फायदे हैं जो लागत के लायक हैं:

1) यह आपको लिखने वाले कोड के लिए विफलता मोड के बारे में सोचने के लिए प्रोत्साहित करता है मूल रूप से, आपको उन अपवादों पर विचार करना होगा जिन्हें आप कहते हैं कि कोड फेंक सकते हैं, और इसके बदले आप अपवादों पर विचार करेंगे जो आप को कॉल करते हैं जो आपको कॉल करता है

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

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

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


@erikson

बस अपने विचारों को खाना जोड़ने के लिए:

चेक किए गए बनाम अनियंत्रित पर भी बहस हुई है

अनियंत्रित अपवादों का उपयोग इस तथ्य के अनुरूप है कि वे समारोह के कॉलर के कारण अपवाद के लिए आईएमओ का इस्तेमाल करते हैं (और कॉलर उस फ़ंक्शन के ऊपर कई परतें हो सकते हैं, इसलिए अपवाद को अनदेखा करने के लिए अन्य फ़्रेमों की आवश्यकता)

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

यह कहा जा रहा है कि अगर अंतर्निहित तकनीक बदलती है, तो वास्तव में आपके पकड़ में आने वाले उन कैच () पर असर होगा, जो आपके नवीनतम परिदृश्य का जवाब नहीं देता है







exception