जावा एप्लिकेशन में रनटाइम अपवाद को फेंकना


12

मैं एक तकनीकी लीड की भूमिका में अपने क्लाइंट के लिए एक एंटरप्राइज़ डिज़ाइनिंग एंटरप्राइज़ जावा एप्लिकेशन के रूप में काम कर रहा हूं। एप्लिकेशन का उपयोग अंतिम उपयोगकर्ताओं द्वारा किया जाएगा और एक समर्थन टीम होगी जो एप्लिकेशन का समर्थन करेगी जब हम छोड़ देंगे।

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

एक व्यावसायिक अनुप्रयोग में कभी भी अनियंत्रित अपवाद को फेंकने की क्या आवश्यकता है?

रनटाइम अपवादों के बारे में अतीत में मेरे अनुभव से:

1) अनियंत्रित अपवाद कोड को अप्रत्याशित बनाते हैं क्योंकि वे जवादोक में भी नहीं दिखाते हैं।

2) एक व्यावसायिक अनुप्रयोग में अनियंत्रित अपवाद फेंकना गैर-समझदारी है क्योंकि जब आप इसे फेंकते हैं और यह सीधे उपयोगकर्ता के चेहरे पर जाता है, तो आप इसे उपयोगकर्ता को कैसे समझाते हैं? मैंने बहुत सारे वेब एप्लिकेशन देखे हैं जो दिखाते हैं 500 -Internal Error. Contact Administratorकि एंड यूज़र के लिए या एप्लिकेशन को प्रबंधित करने वाली सहायता टीम के लिए कुछ भी नहीं है।

३) रनटाइम अपवाद को फेंकने वाले वर्ग के उपयोगकर्ताओं को स्रोत कोड के माध्यम से डिबग करने के लिए चलने के अपवाद को फेंकने के लिए मजबूर करता है और देखें कि अपवाद क्यों फेंका गया है। यह केवल तभी टाला जा सकता है जब रनवे अपवाद के जावदोक को उत्कृष्ट रूप से प्रलेखित किया जाए जो मुझे लगता है कि कभी भी मामला नहीं है।


क्या आप बता सकते हैं कि सर्विस टियर क्या है? क्या परत उपयोगकर्ता से सबसे दूर है, या उपयोगकर्ता के निकटतम है?
मनोज आर

यह सवाल एसओ पर क्यों फिट नहीं बैठता है?
बजर्के फ्रायंड-हेन्सन

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

6
अनियंत्रित अपवाद [...] जवादोक में भी नहीं दिखा। => वे दिखाई देंगे यदि आप उन्हें @throwsटैग के साथ दस्तावेज करते हैं , जो कि एक अच्छा अभ्यास है।
assylias

4
@SureshKoya प्रभावी जावा, आइटम 62: प्रत्येक विधि द्वारा फेंके गए सभी अपवाद दस्तावेज़। निकालें: प्रत्येक अनियंत्रित अपवाद को दस्तावेज़ करने के लिए Javadoc @throwsटैग का उपयोग करें जो कि कोई विधि फेंक सकती है, लेकिन विधि घोषणा में अनियंत्रित अपवादों को शामिल करने के लिए थ्रो कीवर्ड का उपयोग न करें।
assylias

जवाबों:


13

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

अपने अंकों के लिए:

1) चेक किए गए अपवाद कोड को गंदा करते हैं, और कोई अप्रत्याशित नहीं क्योंकि वे हर जगह दिखाते हैं ।

2) उपयोगकर्ता को किसी भी बेहतर तरीके से दिखाया गया एक अपवाद अपवाद कैसे दिखाया जा रहा है? चेक किए गए और अनियंत्रित अपवादों के बीच एकमात्र वास्तविक अंतर तकनीकी है और केवल स्रोत कोड को प्रभावित करता है।

3) कभी स्टैक के निशान के बारे में सुना है? वे आपको बताते हैं कि अपवाद कहां फेंका गया है, कोई फर्क नहीं पड़ता कि यह जांचा गया या अनियंत्रित है। दरअसल, चेक किए गए अपवाद डीबगिंग के लिए बदतर होते हैं क्योंकि वे अक्सर लिपटे होते हैं जो लंबे और बदसूरत स्टैक के निशान की ओर जाता है, या यहां तक ​​कि पूरी तरह से खो जाता है क्योंकि रैपिंग गलत किया गया था।

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

चेक किए गए अपवाद इस बिंदु पर भाषा के सिंटैक्स में इस अंतर को डालने का एक प्रयास था, अपवादों को परिभाषित किया गया है। इसके साथ समस्याएं हैं

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

1. अच्छी तरह से अनियंत्रित अपवाद के मामले में, आपको पता भी नहीं चलेगा कि क्या कोई कॉल अनियंत्रित हो सकती है। 2. जब आपने कहा था "यह अपवाद के अर्थ अर्थ के लिए पूरी तरह से रूढ़िवादी है, लेकिन इसे वर्ग पदानुक्रम के लिए बाध्य करना आपको दोनों को मिलाने के लिए मजबूर करता है", मुझे लगता है कि आपको वर्ग पदानुक्रम के बजाय पदानुक्रम का मतलब था।
randominstanceOfLivingThing

2
@ सुरेश कोया: नहीं, मेरा मतलब वर्ग पदानुक्रम था, इस तथ्य का कि एक घोषणा का SQLException extends Exceptionमतलब है कि SQLExceptionएक त्रुटि को चुनने के लिए क्योंकि डीबी पहुंच के साथ क्या करना है स्वचालित रूप से इसका मतलब है कि अपवाद की जाँच की जाती है। और आप Javadoc टिप्पणियों में अनियंत्रित अपवादों को ठीक से दस्तावेज़ कर सकते हैं। अन्य सभी भाषाओं के लिए अच्छा काम करता है।
माइकल बोर्गवर्ड

1
@MichaelBorgwardt "चेक किए गए अपवाद भाषा डिजाइन में एक असफल विस्तार हैं", क्या यह आपकी व्यक्तिगत राय है यदि मैं इसके बारे में अधिक नहीं पढ़ना चाहूंगा। किसी भी प्रामाणिक लिंक से बहुत मदद मिलेगी।
विपिन

2
@ विपिन: यह मेरी निजी राय है, लेकिन एक जिसे कई अन्य लोग साझा करते हैं, जैसे ब्रूस एकेल : mindview.net/Etc/Discussions/CheckedException - और तथ्य यह है कि जावा को बोलने के बाद 20 वर्षों में किसी अन्य भाषा ने जाँच अपवाद नहीं अपनाया है। खुद के लिए ...
माइकल बोर्गवर्ड

2

मेरा विचार है कि किस प्रकार का अपवाद फेंका गया है, यह इस बात पर निर्भर करता है कि आपका कोड क्या कर रहा है।

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

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

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

मेरा अनुमान है कि आपके द्वारा उल्लिखित दर्शन दो स्रोतों में से एक से आता है:

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

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

मैं आपके दर्शन पर सहमत हूं। एक ऐसे एप्लिकेशन पर जिसे आप उपयोगकर्ताओं के लिए विकसित कर रहे हैं, रनटाइम अपवाद को फेंकने की क्या आवश्यकता होगी?
randominstanceOfLivingThing 15

इसके अलावा, यहां तक ​​कि अगर एक रनटाइम अपवाद को फेंक दिया जाता है, तो मैं उस सम्मेलन को पसंद करता हूं जो @assylias को इंगित किया गया है।
randominstanceOfLivingThing

1

यदि आप अनियंत्रित रनटाइम अपवाद नहीं चाहते हैं, तो आप जावा का उपयोग क्यों कर रहे हैं? लगभग हर जगह रनटाइम अपवाद की संभावना है - विशेष रूप से NullPointerException, ArithmeticException, ArrayIndexOutOfBounds अपवाद, आदि।

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


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

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

1

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

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

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

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

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

एक अपवाद को संभालने का एक तरीका एक और अपवाद है जो समस्या के उच्च-स्तरीय विवरण प्रदान करता है (उदाहरण के लिए, " failed to initialize" के बजाय " index out of bounds")। यह एक अच्छा पैटर्न है जब तक आप अपवाद के कारण के बारे में जानकारी नहीं खोते हैं; causeउच्च-स्तरीय अपवाद को इनिशियलाइज़ करने के लिए विस्तृत अपवाद का उपयोग करें या विवरण लॉग करें (जैसा कि ऊपर चर्चा की गई है)। लॉगिंग सबसे उपयुक्त है जब आप एक अंतर-प्रक्रिया सीमा को पार करने वाले होते हैं, जैसे कि IPC कॉल, क्योंकि इस बात की कोई गारंटी नहीं है कि कनेक्शन के दूसरे छोर पर निम्न-स्तरीय अपवाद वर्ग सभी पर मौजूद होगा। एक आंतरिक सीमा को पार करते समय एक संलग्न कारण के रूप में रखना सबसे उपयुक्त है।

आपके द्वारा देखा गया एक और पैटर्न कैच-एंड-रिलीज़ है:

try {
    // ...
} catch (FooException e) {
    throw e;
}

यह एक विरोधी प्रतिमान है जब तक कि आपको अन्य catchखंडों से प्रकार की बाधाएं नहीं मिली हैं, इसका मतलब है कि आप अपवाद को अपने दम पर अतीत में जाने नहीं दे सकते। तब यह जावा की एक बदसूरत विशेषता है।

चेक किए गए अपवादों के बीच कोई वास्तविक अंतर नहीं है और इस तथ्य के अलावा अनियंत्रित हैं कि आपको चेक अपवादों को घोषित करना चाहिए जो क्रॉस विधि की सीमाएं हैं। @throwsयदि आप जानते हैं कि आपके कोड के द्वारा जानबूझकर फेंका जा रहा है, तो यह अभी भी एक अच्छा विचार है कि अनियंत्रित अपवादों ( javadoc टिप्पणी के साथ) को दस्तावेज़ित किया जाए । जानबूझकर java.lang.Errorया उसके उपवर्गों को न फेंकें (जब तक कि आप एक जेवीएम कार्यान्वयन नहीं लिख रहे हों)।

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


0

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

एक उदाहरण के रूप में,

यदि आपका ऐप किसी फ़ाइल या डेटाबेस से डेटा लोड करता है। फिर,..

try {
  File data = new File(...);
  // parse file here
} catch (Exception ex) {
  throw new MissingDataFileException("data file not found");
}

कॉलर हमेशा चेक किए गए MissingDataFileException को पकड़ सकता है और फिर डेटाबेस से डेटा लोड करने का प्रयास कर सकता है।

try {
  Connection con = DriverManager.getConnection( host, username, password );
  // query data here
} catch (Exception ex) {
  throw new RuntimeException("better call Saul!");
}

1
शाऊल की 3 साल पहले एक कार दुर्घटना में मौत हो गई थी। असफल! ;-)
डोनाल्ड फैलो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.