क्या एक चेक किए गए अपवाद को पकड़ना और RuntimeException को फेंकना अच्छा अभ्यास है?


70

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


17
"चेक किए गए अपवादों की कीमत एक खुला / बंद सिद्धांत उल्लंघन है। यदि आप अपने कोड में एक विधि से एक चेक किए गए अपवाद को फेंक देते हैं और पकड़ तीन स्तरों से ऊपर है, तो आपको अपने और पकड़ने के बीच प्रत्येक विधि के हस्ताक्षर में उस अपवाद को घोषित करना होगा इसका मतलब है कि सॉफ़्टवेयर के निम्न स्तर पर परिवर्तन कई उच्च स्तरों पर हस्ताक्षर परिवर्तनों को बाध्य कर सकता है। " —रॉबर्ट सी। मार्टिन, «स्वच्छ संहिता», पृष्ठ
सोंगो

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

@GlenPeterson आपके पास एफपी में सलाह भी है कि निष्पादनों से पूरी तरह से बचें और इसके बजाय योग के प्रकारों का उपयोग करें
jk।

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

अपने अपवाद के माध्यम से अर्थ संप्रेषित करने के लिए RuntimeException के कस्टम उपवर्ग बनाने में कुछ भी गलत नहीं है।
जोएल कॉर्नेट

जवाबों:


55

मुझे यह जानने के लिए पर्याप्त संदर्भ नहीं है कि आपका सहकर्मी गलत तरीके से कुछ कर रहा है या नहीं, इसलिए मैं सामान्य रूप से इस बारे में बहस करने जा रहा हूं।

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

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

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


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

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

40

यह अच्छा हो सकता है । कृपया पढ़ें:

http://onjava.com/pub/a/onjava/2003/11/19/exceptions.html

अधिकांश समय, क्लाइंट कोड SQLException के बारे में कुछ भी नहीं कर सकता है। उन्हें अनियंत्रित अपवाद में बदलने में संकोच न करें। निम्नलिखित कोड पर विचार करें:

public void dataAccessCode(){
  try{
      ..some code that throws SQLException
  }catch(SQLException ex){
      ex.printStacktrace();
  }
} 

यह कैच ब्लॉक केवल अपवाद को दबाता है और कुछ भी नहीं करता है। औचित्य यह है कि कुछ भी नहीं है मेरा ग्राहक एक SQLException के बारे में कर सकता है। निम्नलिखित तरीके से इससे निपटने के बारे में कैसे?

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
} 

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

चेक किए गए अपवादों को फेंकना और इससे उबरने में सक्षम नहीं होना मदद नहीं कर रहा है।

कुछ लोग यह भी सोचते हैं कि चेक किए गए अपवादों का उपयोग बिल्कुल नहीं किया जाना चाहिए। Http://www.ibm.com/developerworks/java/library/j-jtp05254/index.html देखें

हाल ही में, ब्रूस एकेल और रॉड जॉनसन सहित कई प्रसिद्ध विशेषज्ञों ने सार्वजनिक रूप से कहा है कि जब वे शुरू में जाँच किए गए अपवादों पर रूढ़िवादी स्थिति से पूरी तरह सहमत थे, तो उन्होंने निष्कर्ष निकाला है कि जाँच किए गए अपवादों का अनन्य उपयोग उतना अच्छा नहीं है जितना कि यह एक विचार है। पहली बार में दिखाई दिया, और यह जाँच की अपवाद कई बड़ी परियोजनाओं के लिए समस्याओं का एक महत्वपूर्ण स्रोत बन गए हैं। एक्सेल एक अधिक चरम दृश्य लेता है, यह सुझाव देता है कि सभी अपवादों को अनियंत्रित किया जाना चाहिए; जॉनसन का दृष्टिकोण अधिक रूढ़िवादी है, लेकिन फिर भी यह बताता है कि चेक किए गए अपवादों के लिए रूढ़िवादी वरीयता अत्यधिक है। (यह ध्यान देने योग्य है कि C # के आर्किटेक्ट, जिनके पास निश्चित रूप से जावा तकनीक का उपयोग करने का बहुत अनुभव था, ने भाषा डिजाइन से जांचे गए अपवादों को छोड़ दिया, सभी अपवादों को अनियंत्रित अपवाद बना दिया।

उसी लिंक से भी:

अनियंत्रित अपवादों का उपयोग करने का निर्णय एक जटिल है, और यह स्पष्ट है कि कोई स्पष्ट जवाब नहीं है। सूर्य की सलाह है कि उन्हें बिना किसी चीज के उपयोग करने के लिए, C # दृष्टिकोण (जो एक्सेल और अन्य सहमत हैं) का उपयोग उन्हें हर चीज के लिए करना है। दूसरों का कहना है, "एक बीच का मैदान है।"


13

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


1
संकेत के लिए धन्यवाद। और क्या होगा अगर वह एक कस्टम अपवाद फेंकता है जो उसने लागू किया है जो सीधे RuntimeException से विरासत में मिला है?
RoflcoptrException

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

7
@ गैरी ब्यूएन: यहां एक लेख है जो बहस को बहुत अच्छी तरह से बताता है: ibm.com/developerworks/java/library/j-jtp05254/index.html ध्यान दें कि जावा द्वारा इस सुविधा को पेश किए जाने के 15 साल बाद भी, किसी अन्य भाषा ने इसे नहीं अपनाया है, और C ++ ने इसी तरह की सुविधा को चित्रित किया है।
माइकल बोर्गवर्ड

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

14
अनावश्यक रूप से फेंके गए अपवादों को जांचना उल्लंघन का उल्लंघन करता है। यदि आप 'getAccounts ()' जैसी सरल विधि आपको 'SQLException', 'NullPointerException' या 'FileNotFoundException' की तरह फेंकते हैं, तो आप क्या करते हैं? क्या तुम इसे संभाल लोगे? Youll शायद सिर्फ 'पकड़ (अपवाद e) {}' इसे। इसके अलावा, उन अपवादों - इसके कार्यान्वयन विशिष्ट! यह अनुबंध का हिस्सा नहीं होना चाहिए! आपको बस इतना पता होना चाहिए कि कोई त्रुटि थी । और क्या होगा अगर कार्यान्वयन बदल जाता है? अचानक सब कुछ बदलना पड़ता है, क्योंकि यह विधि अब 'SQLException' को नहीं फेंकती, बल्कि 'ParseXMLException' को फेंक देती है!
केएल

8

निर्भर करता है।

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

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

अन्य समाधान कॉलिंग लेयर में इस चेक किए गए अपवाद को पुनर्विचार करने के लिए हो सकता है, लेकिन यदि आप इसे हल करने में असमर्थ थे, जहां अपवाद हुआ, तो आप संभवतः इसे यहां भी हल करने में असमर्थ होंगे ...


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

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

2
उल्लेख करने के लिए धन्यवाद exception handling layer- जैसे कि एक वेबएप, एक फिल्टर में।
जेक टोरंटो

5

मैं इस पर टिप्पणी प्राप्त करना चाहूंगा, लेकिन मुझे लगता है कि कई बार ऐसा होता है जब यह आवश्यक रूप से बुरा अभ्यास नहीं होता है। (या बहुत बुरा)। लेकिन शायद मैं गलत हूं।

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

RuntimeException को बाद में पकड़ा और नजरअंदाज नहीं किया गया है, यह एक OnErrorResumeNext के पास नहीं है।

OnErrorResumeNext तब होता है जब कोई अपवाद को पकड़ता है और बस इसे अनदेखा करता है या सिर्फ इसे प्रिंट करता है। यह लगभग सभी मामलों में बहुत बुरा व्यवहार है।


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

@MichaelK समस्या "व्यावहारिक के रूप में त्रुटि के करीब है" व्यवहार में अक्सर इसका मतलब है "कई हस्तक्षेप परतों के माध्यम से जो आपके प्रत्यक्ष नियंत्रण से बाहर हैं"। उदाहरण के लिए, यदि मेरी कक्षा को एक निश्चित इंटरफ़ेस लागू करना है, तो मेरे हाथ बंधे हुए हैं। कॉल ट्री में यह मनमाने ढंग से गहरा हो सकता है। यहां तक ​​कि जब इंटरफेस मेरे नियंत्रण में होते हैं, तो थ्रो घोषणाओं को जोड़ने से एब्स्ट्रैक्शन लीक हो सकता है यदि केवल ठोस कार्यान्वयन का एक सीमित सेट होता है जो गर्भ धारण कर सकता है। प्रत्येक ग्राहक को कुछ के कार्यान्वयन के विवरण के लिए लागत का भुगतान करना एक महान डिज़ाइन ट्रेडऑफ़ IMO नहीं है।
टिम सेगिन

4

टी एल; डॉ

परिसर

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

निष्कर्ष

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


यह खंड इस विषय पर चर्चा करता है कि अपवादों को कब फेंका जाना चाहिए। यदि आप निष्कर्ष के लिए अधिक विस्तृत विवरण पढ़ना चाहते हैं, तो आप अगली क्षैतिज पट्टी पर जा सकते हैं।

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

उदाहरण के लिए, निम्न के लिए रनटाइम अपवाद को फेंकना उचित है:

float nan = 1/0;

यह शून्य रनटाइम अपवाद द्वारा एक डिवीजन को फेंक देगा। यह उचित है क्योंकि कोड दोषपूर्ण है।

या उदाहरण के लिए, यहाँ HashMapकंस्ट्रक्टर का एक हिस्सा है :

public HashMap(int initialCapacity, float loadFactor) {
    if (initialCapacity < 0)
        throw new IllegalArgumentException("Illegal initial capacity: " + initialCapacity);
    if (initialCapacity > MAXIMUM_CAPACITY)
        initialCapacity = MAXIMUM_CAPACITY;
    if (loadFactor <= 0 || Float.isNaN(loadFactor))
        throw new IllegalArgumentException("Illegal load factor: " +
                loadFactor);
    // more irrelevant code...
}

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

चेक किए गए अपवाद को फेंकना कब उचित है? जब कोड को बदले बिना समस्या ठीक हो जाए तो आप एक जाँच अपवाद को फेंक देते हैं । या इसे अलग-अलग शब्दों में रखने के लिए, आप त्रुटि की स्थिति से संबंधित अपवाद को एक चेक अपवाद को फेंक देते हैं जब कोड सही होता है।

अब "ठीक" शब्द यहां मुश्किल हो सकता है। इसका मतलब यह हो सकता है कि आपको लक्ष्य प्राप्त करने का एक और तरीका मिल जाए: उदाहरण के लिए, यदि सर्वर जवाब नहीं देता है तो आपको अगले सर्वर की कोशिश करनी चाहिए। यदि आपके मामले में उस तरह की रिकवरी संभव है, तो यह बहुत अच्छा है, लेकिन केवल यही रिकवरी का मतलब नहीं है - रिकवरी केवल उपयोगकर्ता को एक त्रुटि संवाद प्रदर्शित कर सकता है जो बताता है कि क्या हुआ, या यदि वह एक सर्वर एप्लिकेशन है तो यह हो सकता है व्यवस्थापक को एक ईमेल भेजना, या यहां तक ​​कि त्रुटि को उचित और संक्षिप्त रूप से लॉग करना।

आइए उस उदाहरण को लेते हैं जिसका उल्लेख mrmuggles के उत्तर में किया गया था:

public void dataAccessCode(){
   try{
       ..some code that throws SQLException
   }catch(SQLException ex){
       throw new RuntimeException(ex);
   }
}

चेक किए गए अपवाद को संभालने का यह सही तरीका नहीं है। इस विधि के दायरे में अपवाद को संभालने के लिए मात्र अक्षमता का मतलब यह नहीं है कि ऐप को क्रैश कर दिया जाना चाहिए। इसके बजाय, इसे इस तरह उच्च दायरे में प्रचारित करना उचित है:

public Data dataAccessCode() throws SQLException {
    // some code that communicates with the database
}

जो कॉलर द्वारा वसूली की संभावना के लिए अनुमति देता है:

public void loadDataAndShowUi() {
    try {
        Data data = dataAccessCode();
        showUiForData(data);
    } catch(SQLException e) {
        // Recover by showing an error alert dialog
        showCantLoadDataErrorDialog();
    }
}

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

यह भी ध्यान देने योग्य है कि कॉलिंग लेयर में चीजों की grander योजना का बेहतर संदर्भ है जैसा कि ऊपर दिखाया गया है। इसके कई कारण हो सकते हैं dataAccessCode, जिन्हें कॉल किया जाएगा, कॉल का विशिष्ट कारण केवल कॉल करने वाले को दिखाई देता है - इस प्रकार यह विफलता पर सही रिकवरी पर बेहतर निर्णय लेने में सक्षम है।

अब जब हमें यह अंतर स्पष्ट हो गया है, तो जब हम रनटाइम अपवाद के रूप में चेक किए गए अपवाद को फिर से हटाना चाहते हैं, तो हम घटा सकते हैं।


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

निम्नलिखित को धयान मे रखते हुए:

StringReader sr = new StringReader("{\"test\":\"test\"}");
try {
    doesSomethingWithReader(sr); // calls #read, so propagates IOException
} catch (IOException e) {
    throw new IllegalStateException(e);
}

इस उदाहरण में, कोड प्रचारित कर रहा है IOExceptionक्योंकि एपीआई का Readerबाहरी राज्य तक पहुँचने के लिए डिज़ाइन किया गया है, हालाँकि हम जानते हैं कि StringReaderकार्यान्वयन बाहरी राज्य तक नहीं पहुँचता है। इस दायरे में, जहां हम निश्चित रूप से जोर दे सकते हैं कि कॉल में शामिल पुर्जे IO या किसी अन्य बाहरी स्थिति तक नहीं पहुंचते हैं, हम आश्चर्यजनक रूप से अपवाद के रूप में एक अपवाद के रूप में इस अपवाद को हटा सकते हैं जो हमारे कार्यान्वयन से अनजान हैं (और संभवतः यह मानते हुए कि IO-accessing code a IOException) फेंक देगा ।


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


2

स्टैंडअलोन अनुप्रयोगों के लिए। जब आप जानते हैं कि आपका आवेदन चेक किए गए RuntimeException को फेंकने के बजाय आपके द्वारा किए गए अपवाद को नहीं संभाल सकता है, तो त्रुटि को फेंकें, एप्लिकेशन को क्रैश होने दें, बग-रिपोर्ट की आशा करें और अपना एप्लिकेशन ठीक करें। (देखें जवाब की mrmuggles समर्थक है और चोर के बनाम अनियंत्रित जाँच की की और गहरी में चर्चा के लिए।)


2

यह कई रूपरेखाओं में आम बात है। जैसे Hibernateठीक यही करता है। विचार यह है कि एपीआई ग्राहक पक्ष के लिए घुसपैठ नहीं करना चाहिए और Exceptionघुसपैठ कर रहे हैं क्योंकि आपको उस जगह पर उन्हें संभालने के लिए स्पष्ट रूप से कोड लिखना होगा जहां आप एपी कहते हैं। लेकिन पहली जगह में अपवाद को संभालने के लिए वह जगह सही जगह नहीं हो सकती है।
वास्तव में ईमानदार होना यह एक "गर्म" विषय है और बहुत से विवाद हैं इसलिए मैं इसका पक्ष नहीं लूंगा लेकिन मैं कहूंगा कि आपका मित्र जो करता है / प्रस्ताव करता है वह सामान्य या असामान्य नहीं है।


1

पूरी "जाँच अपवाद" बात एक बुरा विचार है।

संरचित प्रोग्रामिंग केवल सूचनाओं को कार्य के बीच (या, जावा पैरलेंस, विधियों में) पास करने की अनुमति देती है, जब वे "पास" होते हैं। अधिक सटीक रूप से, जानकारी केवल दो तरीकों से कार्य कर सकती है:

  1. कॉलगर्ल से लेकर कैली तक, तर्क पारित करने के माध्यम से।

  2. कैली से लेकर इसके कॉलर तक, रिटर्न मान के रूप में।

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

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

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


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

0

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

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

उदाहरण के लिए Integer.parseInt (स्ट्रिंग) एक स्ट्रिंग लेता है और इसके बराबर पूर्णांक लौटाता है और स्ट्रिंग के संख्यात्मक नहीं होने की स्थिति में नंबरफार्मेट को फेंकता है। अब कल्पना करें कि किसी फ़ील्ड के साथ एक फ़ॉर्म सबमिशन ageइस विधि के माध्यम से परिवर्तित किया जाता है, लेकिन क्लाइंट पहले से ही इसकी ओर से सत्यापन सुनिश्चित कर चुका होता है, इसलिए अपवाद की जाँच के लिए कोई मतलब नहीं है।


0

यहाँ वास्तव में कुछ सवाल हैं

  1. क्या आपको चेक किए गए अपवादों को अनियंत्रित लोगों में बदलना चाहिए?

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

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

  1. यदि आप एक अनियंत्रित अपवाद को चेक किए गए अपवाद में बदलने जा रहे हैं तो आपको यह कैसे करना चाहिए।

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

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


0

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

वर्षों से मैंने पाया कि किसी को हमेशा एक तुच्छ समस्या के बारे में उलझन होती है, जिसमें उन्हें कुछ बुनियादी बातों की समझ की कमी होती है।

लेयरिंग। एक सॉफ्टवेयर एप्लीकेशन (कम से कम माना जाता है) एक के ऊपर एक परतों का ढेर। अच्छी परत के लिए एक महत्वपूर्ण अपेक्षा यह है कि निचली परतें ऊपरी परत से संभावित कई घटकों के लिए कार्यक्षमता प्रदान करती हैं।

मान लीजिए कि आपके ऐप में नीचे की तरफ़ नेट, टीसीपी, HTTP, REST, DATA MODEL, BUSINESS है।

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

क्या अधिक है, अगर मैं विवरण जानता हूं तो यह बुरा है, क्योंकि अगर कल मैं टीसीएल प्रोटोकॉल के लिए विशिष्ट विवरणों से निपटने वाले रेखांकित परिवहन प्रोटोकॉल को बदलना चाहूंगा तो इसका मतलब यह है कि मेरे बाकी अमूर्त ने खुद को अमूर्त करने के लिए एक अच्छा काम नहीं किया है। विशिष्ट कार्यान्वयन।

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

निश्चित रूप से, आपके द्वारा बताए गए वास्तविक स्थान एक अलग कहानी है, लेकिन सामान्य रूप से - हां, यह एक अच्छी बात हो सकती है।


-2

मेरी राय में,

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

आवेदन स्तर में, हम शायद ही कभी रनटाइम अपवादों पर कब्जा करते हैं और मुझे लगता है कि यह अभ्यास खराब था।


1
और फ्रेमवर्क स्तर पर आप उन अपवादों का क्या करेंगे?
मैथ्यू

यदि फ्रेमवर्क में एक यूआई परत है जो अपवादों को संभाल सकती है, तो यूआई किसी तरह का त्रुटि संदेश पेश करेगा कि कुछ गलत हो गया है। एक-पृष्ठ जावास्क्रिप्ट ऐप के मामले में, ऐप एक त्रुटि संदेश प्रस्तुत कर सकता है। दी गई, यूआई परत को त्रुटि को तभी संभालना चाहिए जब गहरी परत वास्तव में त्रुटि से उबर नहीं सकती है।
जेक टोरंटो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.