2017-11-16 72 views
5

एक PHP दुनिया में जहां सिर्फ एक ही रास्ता निपटने अपवाद लिखने के लिए नहीं है .. मैं जावा में एक सा "बदसूरत" अपवादों की रैपिंग पाया से आ रहा है:जावा अपवाद लपेटना: खराब अभ्यास?

public void exampleOneException(String input) throws MyBusinessException { 
    try { 
     // do something 
    } catch (NumberFormatException e) { 
     throw new MyBusinessException("Error...", e); 
    } 
} 

मैं बजाय इस शैली का उपयोग करना पसंद करते हैं:

public void exampleTwoException() { 
    try { 
     // do something 
    } catch (MyBusinessException e) { 
     log.error("Error...: " + e); 
    } catch (NumberFormatException e) { 
     log.error("Error...: " + e); 
    } 
} 

क्या अपवादों को संभालने के उन दृष्टिकोणों पर कोई अंतर या सर्वोत्तम प्रथा है?

+0

'उदाहरणऑनएक्सप्शन' कहने वाले तरीके 'MyBusinessException' को पकड़ सकते हैं और इसे अपनी आवश्यकताओं के अनुसार संभाल सकते हैं। 'ExampleTwoException' को कॉल करने के तरीके के बारे में जानने का कोई तरीका नहीं है कि कुछ भी गलत हो गया है। – khelwood

+2

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

+1

वे दो कोड स्निपेट एक ही काम नहीं कर रहे हैं। एक में आप दूसरे में अपवाद को फिर से जोड़ रहे हैं, आप इसे लॉगिंग कर रहे हैं। –

उत्तर

5

ये दोनों अलग-अलग परिदृश्यों के लिए मान्य दृष्टिकोण हैं।

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

दूसरे परिदृश्य में, आप अपवाद और लॉग पकड़ते हैं यह, कॉलर से विफलता को प्रभावी ढंग से छुपा रहा है। ऑपरेशन सफल होने पर या नहीं, अगर कॉलर वास्तव में परवाह नहीं करता है तो इस प्रकार की हैंडलिंग उपयोगी हो सकती है।

+1

यदि आप निश्चित हैं कि ऑपरेशन सफल होगा तो आप क्लॉज को पकड़ने के लिए कुछ भी नहीं लिख सकते हैं।इसे खराब प्रोग्रामिंग के रूप में माना जाता है लेकिन फिर भी व्यापक रूप से उपयोग किया जाता है क्योंकि लोग आलसी हैं ^^ –

1

मैं कहूंगा कि NumberFormatException और MyBusinessException उपयोगी हैं लेकिन विभिन्न मामलों में उपयोगी हैं।

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

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

अपवादों का उपयोग करने में सर्वोत्तम अभ्यास का पालन करने के तरीके के बारे में विवरण के लिए, Item 61 - Throw exceptions appropriate to the abstractionEffective Java by Joshua Bloch से पढ़ें।

3

पहला उदाहरण आमतौर पर बेहतर दृष्टिकोण के रूप में देखा जाएगा।

तुम भी विचार करना चाहिए नहीं MyBusinessExceptionNumberFormatException लपेटकर होने के लिए, बल्कि NumberFormatExceptionMyBusinessException की कारण है।

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

एक और ठोस उदाहरण में आम तौर पर भिन्न कार्यान्वयन शामिल होते हैं, जहां इंटरफ़ेस के उपयोगकर्ताओं को कार्यान्वयन विनिर्देशों (जिसे संकलन समय पर भी ज्ञात नहीं किया जा सकता है) से निपटने के लिए आवश्यक नहीं होना चाहिए।

interface MyRepository { 
    Object read(int id) throws ObjectNotFoundException; 
} 

// a sql backed repository 
class JdbcRepository implements MyRepository { 
    public Object read(int id) throws ObjectNotFoundException { 
     try { ... } 
     catch (SQLException ex) { 
      throw new ObjectNotFoundException(ex); 
     } 
    } 
} 

// a file backed repository 
class FileRepository implements MyRepository { 
    public Object read(int id) throws ObjectNotFoundException { 
     try { ... } 
     catch (FileNotFoundException ex) { 
      throw new ObjectNotFoundException(ex) 
     } 
    } 
} 

क्योंकि इंटरफ़ेस त्रुटियों यह लौट सकते हैं के प्रकार वाणी, कि अंतरफलक के ग्राहकों सुसंगत और तर्कसंगत हो सकता है। FileNotFoundException और SQLException को संभालने के लिए कोड जोड़ना, तो वास्तविक कार्यान्वयन या तो हो सकता है, या न तो शानदार नहीं है।

विचार करें कि FileRepository के कार्यान्वयन में कई जगहें हैं जो FileNotFoundException फेंक सकती हैं। क्या इसका मतलब है कि उनमें से हर एक का तात्पर्य है ऑब्जेक्ट नहीं मिला?

विकल्प दो, exampleTwoException पर विचार करते समय, यह जानना महत्वपूर्ण है कि आपका catch ब्लॉक प्रभावी ढंग से बता रहा है कि जो भी त्रुटि हुई है, उसके प्रभाव कम हो गए हैं। वहाँ मामलों में जहां जांचे हुए अपवादों यथोचित ध्यान नहीं दिया जाता हैं, लेकिन यह है कि एक साधारण

try { ... } 
catch (SomeException ex) { 
    log.error("caught some exception", ex); 
} 

वास्तव में अपवाद के परिणामों पर विचार नहीं एक डेवलपर का परिणाम है, या कोड एक को शामिल किया है चाहिए कहीं अधिक होने की संभावना है FIXME

यह और भी सत्य है जब आप catch (Exception ex) देखते हैं, या unconscionable catch (Throwable ex)

और आखिरकार, क्या आप उन सभी स्थानों को खोजने के लिए एक व्यक्ति बनना चाहते हैं जहां आपको एक नया कार्यान्वयन संभालने के लिए एक और पकड़ ब्लॉक जोड़ने की आवश्यकता है? शायद कि catch (Exception ex) का एक कारण है ...

हमेशा फेंक अपवाद अमूर्त

0

स्वच्छ और ठोस कोड के नजरिए आप सही दिशा ड्राइविंग नहीं कर रहे हैं से करने के लिए उपयुक्त।
सबसे पहले आपको Exception के लिए प्रयास/पकड़ने की आवश्यकता नहीं है जो पहले से ही विधि के शीर्षलेख द्वारा फेंक दिया गया है। तो आपके पहले मामले में कोड नीचे जैसा होना चाहिए:

public void exampleOneException(String input) throws MyBusinessException { 
    // do something 
} 

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

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

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

+0

अंत में उपयोग करने की आवश्यकता होने पर प्रयास/पकड़ की आवश्यकता होती है: जैसे कि मैं जावा कचरा कलेक्टर पर निर्भर होने के बजाय डीबी कनेक्शन बंद करना चाहता हूं। – numediaweb

+0

बस स्पष्टीकरण: यदि आप अपवाद को संभालना चाहते हैं तो कोशिश/पकड़ की आवश्यकता है। यदि आपको प्रचार या हैंडलिंग की परवाह नहीं है तो आप विधि के शीर्ष पर 'थ्रो' का उपयोग कर सकते हैं। 'आखिरकार' का उपयोग करके एक हैंडलिंग इरादा पेश करता है। –

+0

अच्छी तरह से अगर हम कोड की गुणवत्ता की परवाह करते हैं और इसलिए लिफ्टिंग लाइब्रेरी (सोनारलिंट) का उपयोग करते हैं तो आखिरकार "अच्छा अभ्यास" का उपयोग करते हैं या हम लिटर को एक त्रुटि दिखाएंगे: "संसाधन बंद होना चाहिए" .. लेकिन यह एक और विषय है .. – numediaweb

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