क्या कोड में रनटाइम अपवादों को संभालना एक अच्छा अभ्यास नहीं है?


11

मैं एक जावा एप्लिकेशन पर काम कर रहा हूं, और मैं देखता हूं कि कई स्थानों पर रन टाइम अपवादों को नियंत्रित किया जाता है। उदाहरण के लिए,

try {
    // do something
} catch(NullPointerException e) {
    return null;
}

मेरा सवाल यह है कि रनटाइम अपवादों को संभालने के लिए एक अच्छा अभ्यास कब है? अपवादों को कब छोड़ देना चाहिए?


7
-1: इस व्यापक और अस्पष्ट सवाल का एक भी जवाब नहीं है। एक प्रश्न का एक भी उत्तर प्रदान करना असंभव है, क्योंकि यह इस प्रकार स्पष्ट नहीं है। यह सवाल भयानक है। कृपया विशिष्ट उदाहरण प्रदान करें जहाँ आपको संदेह है।
S.Lott

@ S.Lott मैं इस मामले में असहमत हूं क्योंकि ऐसा लगता है कि प्रोग्रामरों का एक सबसेट है जो उनके सिर में है कि यह "अच्छा" तर्कसंगतता के साथ मामला है।
सॉयलेंटग्रे 19

2
@Chad: "यह मामला" अच्छा "तर्कसंगतता" के साथ नहीं है। यह सच हो सकता। लेकिन एकमात्र संभावित उत्तर "यह निर्भर करता है" होना चाहिए। इसलिए, प्रश्न दोषपूर्ण लगता है।
एस.लॉट

जवाबों:


18

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

उदाहरण के लिए, Integer#parseIntथ्रो NumberFormatException(जो कि एक आरटीई है) यदि प्रदान की गई स्ट्रिंग को पार्स नहीं किया जा सकता है। लेकिन निश्चित रूप से आप नहीं चाहते हैं कि आपका ऐप केवल दुर्घटनाग्रस्त हो जाए क्योंकि उपयोगकर्ता ने "x" एक पाठ फ़ील्ड पर लिखा था जो पूर्णांक के लिए था? और आप कैसे जानते हैं कि क्या स्ट्रिंग को पार्स किया जा सकता है, जब तक कि आप इसे पहले पार्स करने की कोशिश नहीं करते हैं? तो इस मामले में, आरटीई केवल एक त्रुटि संकेत है जो किसी प्रकार के त्रुटि संदेश का कारण होना चाहिए। कोई यह तर्क दे सकता है कि यह एक जाँच अपवाद होना चाहिए , लेकिन आप क्या कर सकते हैं - यह नहीं है।


2
मैं "यह निर्भर करता है" से सहमत हूं, लेकिन आपका पार्सिंग उदाहरण खराब एपीआई डिजाइन का मामला है। Integer#parseIntवास्तव में Maybe<Integer>इसके बजाय वापस आना चाहिए और किसी भी अपवाद को बिल्कुल नहीं फेंकना चाहिए ।
जॉर्ग डब्ल्यू मित्तग

3
@ Jörg W Mittag: मैं मानता हूं कि यह खराब एपीआई डिजाइन है, लेकिन यह वास्तविक दुनिया है जिससे हमें निपटना है। फेंकवे / रिटर्न वैल्यू को सही तरीके से कैसे संभालना है , यह इस बात पर निर्भर करता है कि दुनिया वास्तव में कैसे काम करती है, न कि यह कैसे बेहतर तरीके से काम करना चाहिए :-)
जूनून पुलकका

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

7

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

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

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


1
मैं जोड़ना चाहूंगा कि एक अशक्त जांच एक बेहतर निर्णय प्रदर्शन-वार है।
महमूद होसम

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

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

newstd::bad_allocC ++ में फेंकता है।
आर। मार्टिनो फर्नांडीस

यह मानते हुए कि नया ऑपरेटर अतिभारित नहीं है, जो आम बात है। C ++ में, कुछ भी हो सकता है;) लेकिन ठीक है, चलो C का मॉलोक कहते हैं। महत्वपूर्ण बात यह थी कि जावा में आपको वह कभी नहीं मिला।
deadalnix

4

मैं अपेक्षित अपवादों को संभालता हूं जहां मैं उनसे उम्मीद करता हूं। (जैसे डीबी रीड / राइट एरर)। अप्रत्याशित अपवाद मैं बबल अप करता हूं। कहीं और अपवाद की अपेक्षा की जा सकती है और इसके लिए तर्क हो सकते हैं।


2

अपवाद सिर्फ इतना होना चाहिए .. अपवाद। अपवादों का उपयोग करते समय सबसे अच्छा अभ्यास उन परिस्थितियों को कवर करने के लिए उनका उपयोग करना है जिसमें कुछ ऐसा होता है जो आप होने की उम्मीद करेंगे। क्लासिक उदाहरण FileNotFoundException है, जो तब फेंक दिया जाता है जब कोई फ़ाइल बस वहाँ नहीं होती है। यदि आप फ़ाइल के अस्तित्व का परीक्षण कर रहे हैं, तो आप File.exists () का उपयोग करते हैं क्योंकि आप बस 10 फुट स्टिक के साथ प्रेषण कर रहे हैं यदि आप कुछ हिट करते हैं।

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

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

उदाहरण के लिए:

Integer getUserCount() {
   Integer result = null;
   try {
      // Attempt to open database and retrieve data
   } catch (TimeoutException e) {
      logger.error("Got a watch?");
   } catch (MissingDatabaseException e) {
      logger.error("What are you smoking?");
   } catch (PermissionsToReadException e) {
      logger.error("Did you *really* think you were getting away with that?");
   } catch (PressedSendButtonToHardException e) {
      logger.error("Seriously.. just back away from the computer... slowly..");
   } catch (WTFException e) {
      logger.error("You're on your own with this one.. I don't even know what happened..");
   } finally {
      // Close connections and whatnot
   }
   return result;
}

void doStuff() {
   Integer result = getUserCount();
   if(result != null) {
       // Went as planned..
   }
}

6
यदि आप File.exists () का उपयोग करते हैं और परिणाम पर भरोसा करते हैं, तो एक रेस स्थिति हो सकती है यदि फ़ाइल File.exists () और File.open () के बीच सही हटा दी जाती है। यदि यह सुरक्षा-महत्वपूर्ण बग को ट्रिगर करता है, तो एक हमलावर उद्देश्य से इस स्थिति का कारण बन सकता है। इस वजह से, ऑपरेशन को परमाणु रखना कभी-कभी बेहतर होता है, अर्थात इसे आज़माएं और अपवाद को पकड़ें।
user281377

1
इसके अलावा, ऐसी फाइलें हैं जो एप्लिकेशन को चलाने के लिए मौजूद होनी चाहिए। वे असाधारण स्थितियाँ होंगी। यदि एप्लिकेशन के कार्य करने के लिए आपके पास एक फ़ाइल होनी चाहिए, तो इसका कोई कारण नहीं है कि इसे पढ़ें और फिर असाधारण मामले के अपवाद को न संभालें। मेरा मानना ​​है कि यह इरादे को और स्पष्ट करता है।
थॉमस ओवेन्स

यह अशक्त लौटने का एक बुरा निर्णय है। यह कुछ बिंदु पर NullPointerException में परिणाम देगा और जो गलत हो गया है उसे डीबग करना वास्तव में कठिन होगा। क्योंकि कोई व्यक्ति किसी बिंदु पर शून्य जांच को भूल जाएगा।
डेडलिंक

@deadalnix: मैं तर्क दे सकता हूं कि आप आसानी से कोशिश करने के साथ-साथ आसानी से घेरना भी भूल सकते हैं। अंतर शैली का विषय है, कार्यक्षमता का नहीं।
नील

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

-5

हाँ, आप सही हैं रन टाइम के अपवादों को संभालना एक अच्छा अभ्यास नहीं है। इसका कारण यह है कि इसे महंगा / मेमोरी इंटेंसिव माना जाता है।


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