एक विधि को कई प्रकार के चेक किए गए अपवादों को क्यों नहीं फेंकना चाहिए?


47

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

सार्वजनिक तरीकों को एक चेक किए गए अपवाद पर फेंकना चाहिए

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

कॉल करने वालों के लिए जटिलता को उचित रखने के लिए, तरीकों को एक से अधिक प्रकार के चेक किए गए अपवाद को नहीं फेंकना चाहिए। "

सोनार में एक और बिट यह है :

सार्वजनिक तरीकों को एक चेक किए गए अपवाद पर फेंकना चाहिए

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

कॉल करने वालों के लिए जटिलता को उचित रखने के लिए, तरीकों को एक से अधिक प्रकार के चेक किए गए अपवाद को नहीं फेंकना चाहिए।

निम्नलिखित कोड:

public void delete() throws IOException, SQLException {      // Non-Compliant
  /* ... */
}

में refactored किया जाना चाहिए:

public void delete() throws SomeApplicationLevelException {  // Compliant
    /* ... */
}

इस नियम से ओवरराइडिंग विधियों की जाँच नहीं की जाती है और कई जाँच अपवादों को फेंकने की अनुमति दी जाती है।

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

क्या यह एक अच्छी तरह से स्वीकृत मानक है?


7
क्या करते हैं आप सोचते हैं? सोनारक्यूब से उद्धृत स्पष्टीकरण आपको समझदार लगता है; क्या आपके पास इस पर संदेह करने का कोई कारण है?
रॉबर्ट हार्वे

3
मैंने बहुत सारे कोड लिखे हैं जो एक से अधिक अपवादों को फेंकते हैं और कई पुस्तकालयों का उपयोग किया है जो एक से अधिक अपवाद भी फेंकते हैं। इसके अलावा, अपवाद हैंडलिंग पर पुस्तकों / लेखों में, फेंके गए अपवादों की संख्या को सीमित करने का विषय आमतौर पर नहीं लाया जाता है। लेकिन कई उदाहरण अभ्यास के लिए एक अंतर्निहित स्वीकृति देते हुए कई फेंकते / पकड़ते हैं। इसलिए, मैंने नियम को आश्चर्यचकित किया और उदाहरणों के आधार पर अपवादों को संभालने की सर्वोत्तम प्रथाओं / दर्शन पर अधिक शोध करना चाहता था।
21

जवाबों:


32

आइए उस स्थिति पर विचार करें जहां आपके पास प्रदान किया गया कोड है:

public void delete() throws IOException, SQLException {      // Non-Compliant
  /* ... */
}

यहां खतरा यह है कि कोड जिसे आप कॉल करने के लिए लिखते हैं, delete()वह दिखेगा:

try {
  foo.delete()
} catch (Exception e) {
  /* ... */
}

यह भी बुरा है। और यह एक अन्य नियम के साथ पकड़ा जाएगा जो बेस एक्सेप्शन क्लास को झंडे को पकड़ता है।

कुंजी कोड लिखना नहीं है जो आपको बुरा कोड कहीं और लिखना चाहता है।

नियम जो आप सामना कर रहे हैं, बल्कि एक आम है। चेकस्टाइल में इसके डिजाइन नियम हैं:

ThrowsCount

प्रतिबंधित एक निर्दिष्ट गिनती (डिफ़ॉल्ट रूप से 1) के लिए कथन फेंकता है।

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

यह समस्या का सटीक वर्णन करता है और समस्या क्या है और आपको ऐसा क्यों नहीं करना चाहिए। यह एक अच्छी तरह से स्वीकार किया गया मानक है कि कई स्थैतिक विश्लेषण उपकरण पहचान और ध्वज लगाएंगे।

और जब आप इसे भाषा डिजाइन के अनुसार कर सकते हैं, और कई बार ऐसा हो सकता है जब यह करना सही है, तो यह कुछ ऐसा है जिसे आपको देखना चाहिए और तुरंत "उम, मैं ऐसा क्यों कर रहा हूं?" यह आंतरिक कोड के लिए स्वीकार्य हो सकता है जहां सभी को कभी भी अनुशासित नहीं किया जाता है catch (Exception e) {}, लेकिन अधिक बार मैंने नहीं देखा है कि लोगों ने विशेष रूप से आंतरिक स्थितियों में कोनों को काट दिया है।

अपने वर्ग का उपयोग करने वाले लोगों को बुरा कोड लिखना न दें।


मुझे यह बताना चाहिए कि जावा एसई 7 के साथ इसका महत्व कम हो जाता है और बाद में क्योंकि एक एकल कैच स्टेटमेंट कई अपवादों को पकड़ सकता है ( ओरेकल से बेहतर टाइप चेकिंग के साथ कई एक्सेप्शन टाइप और रीथ्रोइंग एक्सेप्शन को पकड़ना )।

जावा 6 और इससे पहले, आपके पास ऐसा कोड होगा जो दिखता था:

public void delete() throws IOException, SQLException {
  /* ... */
}

तथा

try {
  foo.delete()
} catch (IOException ex) {
     logger.log(ex);
     throw ex;
} catch (SQLException ex) {
     logger.log(ex);
     throw ex;
}

या

try {
    foo.delete()
} catch (Exception ex) {
    logger.log(ex);
    throw ex;
}

जावा 6 के साथ इनमें से कोई भी विकल्प आदर्श नहीं हैं। पहला दृष्टिकोण DRY का उल्लंघन करता है । एक ही काम कर रहे कई ब्लॉक, बार-बार - प्रत्येक अपवाद के लिए एक बार। आप अपवाद को लॉग इन करना चाहते हैं और इसे रीथ्रो करना चाहते हैं? ठीक। प्रत्येक अपवाद के लिए कोड की समान पंक्तियाँ।

दूसरा विकल्प कई कारणों से खराब है। सबसे पहले, इसका मतलब है कि आप सभी अपवादों को पकड़ रहे हैं। नल पॉइंटर वहां पकड़ा जाता है (और ऐसा नहीं होना चाहिए)। इसके अलावा, आप एक Exceptionजिसका अर्थ यह है कि विधि हस्ताक्षर हो जाएगा deleteSomething() throws Exceptionजो बस एक गड़बड़ आगे ढेर हो जाता है, क्योंकि आपके कोड का उपयोग करने वाले लोग अब मजबूर हो रहे हैं catch(Exception e)

जावा 7 के साथ, यह उतना महत्वपूर्ण नहीं है क्योंकि आप इसके बजाय कर सकते हैं:

catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

इसके अलावा, यदि जाँच की जा रही है कि कोई अपवाद के प्रकार को नहीं पकड़ता है:

public void rethrowException(String exceptionName)
throws IOException, SQLException {
    try {
        foo.delete();
    } catch (Exception e) {
        throw e;
    }
}

प्रकार चेकर पहचान जाएगा कि केवल प्रकार के या eहो सकता है । मैं अभी भी इस शैली के उपयोग के बारे में अधिक उत्साही नहीं हूं, लेकिन यह जावा 6 के तहत खराब कोड के रूप में पैदा नहीं कर रहा है (जहां यह आपको मजबूर कर देगा कि विधि हस्ताक्षर सुपरक्लास हो जो अपवादों का विस्तार करते हैं)।IOExceptionSQLException

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

अपवाद जाँच की जानी चाहिए, तो या अनियंत्रित ... कि की बात है जी आर एक टी बहस है कि एक आसानी से तर्क के प्रत्येक पक्ष लेने के अनगिनत ब्लॉग पोस्ट पा सकते हैं। हालाँकि, यदि आप जाँच किए गए अपवादों के साथ काम कर रहे हैं, तो आपको संभवतः कई प्रकार के फेंकने से बचना चाहिए, कम से कम जावा 6 के तहत।


इसे उत्तर के रूप में स्वीकार करना क्योंकि यह मेरे प्रश्न का उत्तर देता है कि यह एक अच्छी तरह से स्वीकृत मानक है। हालाँकि, मैं अभी भी विभिन्न प्रो / कांग्रेस चर्चाओं को पढ़ रहा हूं, जो लिंक में शुरू होती हैं, जो मेरे मानक क्या होंगे, यह निर्धारित करने के लिए उनके जवाब में प्रदान की गई।
21

"टाइप चेकर पहचान लेगा कि ई केवल IOException या SQLException प्रकार का हो सकता है।": इसका क्या मतलब है? क्या होता है जब एक अन्य प्रकार के अपवाद को फेंक दिया जाता है foo.delete()? क्या यह अभी भी पकड़ा गया है और पुनर्विचार किया गया है?
जियोर्जियो

@ जियोर्जियो यह एक संकलित समय त्रुटि होगी यदि deleteउस उदाहरण में IOException या SQLException के अलावा किसी अन्य अपवाद को जाँचता है। मुख्य बिंदु जो मैं बनाने की कोशिश कर रहा था वह यह है कि एक विधि जिसे rethrowException कहते हैं, अभी भी जावा 7 में अपवाद का प्रकार मिलेगा। जावा 6 में, उस सभी को सामान्य Exceptionप्रकार में विलय कर दिया जाता है जो स्थिर विश्लेषण और अन्य कोडर को दुखी करता है।

समझा। यह मुझे थोड़ा जटिल लगता है। मुझे इसे मना करने catch (Exception e)और इसे catch (IOException e)या catch (SQLException e)इसके बजाय मजबूर करने के लिए अधिक सहज मिलेगा ।
जियोर्जियो

@ जियोर्जियो जावा 6 से एक वृद्धिशील कदम है जो अच्छे कोड लिखने के लिए आसान बनाने की कोशिश करता है। दुर्भाग्य से, बुरा कोड लिखने का विकल्प हमारे साथ लंबे समय तक रहेगा। याद रखें कि जावा 7 catch(IOException|SQLException ex)इसके बजाय कर सकता है । लेकिन, यदि आप केवल अपवाद को पुनर्जीवित करने जा रहे हैं, तो टाइप चेकर को वास्तविक प्रकार के अपवाद को फैलाने की अनुमति देता है, जिससे कोड को सरल बनाने वाली wile एक खराब चीज नहीं है।

22

आदर्श रूप से, आप केवल एक प्रकार के अपवाद को फेंकना चाहते हैं, क्योंकि ऐसा करना संभव है, क्योंकि एकल उत्तरदायित्व और निर्भरता व्युत्क्रम सिद्धांतों का उल्लंघन करता है । प्रदर्शन के लिए एक उदाहरण का उपयोग करते हैं।

मान लीजिए कि हमारे पास एक विधि है जो दृढ़ता से डेटा प्राप्त करती है, और यह दृढ़ता फ़ाइलों का एक समूह है। चूंकि हम फ़ाइलों के साथ काम कर रहे हैं, इसलिए हमारे पास एक हो सकता है FileNotFoundException:

public String getData(int id) throws FileNotFoundException

अब, हमारे पास आवश्यकताओं में बदलाव है, और हमारा डेटा एक डेटाबेस से आता है। के बजाय एक FileNotFoundException(जब से हम फ़ाइलों के साथ काम नहीं कर रहे हैं), हम अब एक फेंक SQLException:

public String getData(int id) throws SQLException

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

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

public String getData(int id) throws InvalidRecordException

अब, यदि हम आंतरिक कार्यान्वयन को बदलते हैं, तो हम केवल उस अपवाद को लपेट सकते हैं InvalidRecordExceptionऔर इसे पास कर सकते हैं (या इसे लपेट नहीं सकते, और बस एक नया फेंक सकते हैं InvalidRecordException)। बाहरी कोड यह नहीं जानता या परवाह नहीं करता है कि किस प्रकार की दृढ़ता का उपयोग किया जा रहा है। यह सब इनकैप्सुलेटेड है।


सिंगल रिस्पॉन्सिबिलिटी के लिए, हमें ऐसे कोड के बारे में सोचना होगा जो कई, असंबंधित अपवादों को फेंकता है। मान लें कि हमारे पास निम्नलिखित विधि है:

public Record parseFile(String filename) throws IOException, ParseException

इस विधि के बारे में हम क्या कह सकते हैं? हम केवल हस्ताक्षर से बता सकते हैं कि यह एक फ़ाइल खोलता है और इसे पार्स करता है। जब हम किसी विधि के विवरण में "और" या "या" जैसे संयुग्मन देखते हैं, तो हम जानते हैं कि यह एक से अधिक कार्य कर रहा है; इसकी एक से अधिक जिम्मेदारी है । एक से अधिक ज़िम्मेदारियों वाले तरीकों को प्रबंधित करना कठिन होता है क्योंकि यदि कोई ज़िम्मेदारियाँ बदलती हैं तो वे बदल सकते हैं। इसके बजाय, हमें तरीकों को तोड़ना चाहिए ताकि उनकी एक ही जिम्मेदारी हो:

public String readFile(String filename) throws IOException
public Record parse(String data) throws ParseException

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


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


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

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

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

+1: मुझे यह उत्तर बहुत पसंद है, विशेष रूप से क्योंकि यह समस्या को एक मॉडलिंग दृष्टिकोण से निपटता है। अक्सर यह अभी तक एक और मुहावरे (जैसे catch (IOException | SQLException ex)) का उपयोग करने के लिए आवश्यक नहीं है क्योंकि वास्तविक समस्या प्रोग्राम मॉडल / डिज़ाइन में है।
जियोर्जियो

3

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

http://tutorials.jenkov.com/java-exception-handling/checked-or-unchecked-exceptions.html

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

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

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

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


2
क्यों न केवल Throwableअपने खुद के पदानुक्रम का आविष्कार करने के बजाय, फेंकता घोषित करें , और उसके साथ किया जाए?
डेडुप्लिकेटर

@Deduplicator इस तरह का कारण है कि लेखक को यह विचार पसंद नहीं आया; आपको लगा कि आप सभी अनियंत्रित उपयोग कर सकते हैं, यदि आप ऐसा करने जा रहे हैं। लेकिन अगर एपीआई का उपयोग करने वाले (संभवतः आपके सहकर्मी) के पास सभी उपवर्गों के अपवादों की एक सूची है जो आपके आधार वर्ग से प्राप्त होते हैं, तो मैं कम से कम लाभ में थोड़ा सा लाभ देख सकता हूं जिससे उन्हें पता चल सके कि सभी अपेक्षित अपवाद हैं उपवर्गों के एक निश्चित सेट के भीतर; तब यदि उन्हें ऐसा लगता है कि उनमें से एक दूसरे की तुलना में अधिक "हैंडलेबल" है, तो वे इसके लिए एक हैंडलर विशिष्ट के लिए प्रवण नहीं होंगे।
Panzercrisis

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

1
@Deduplicator मैं इस विचार का समर्थन नहीं कर रहा हूँ, और मैं आवश्यक रूप से इसका समर्थन नहीं करता। मैं सिर्फ उस दिशा के बारे में बात कर रहा हूं, जहां ओपी को जो सलाह दी गई थी, वह शायद आ रही है।
पैंजरक्रिसिस

1
लिंक के लिए धन्यवाद। इस विषय पर पढ़ने के लिए यह एक शानदार शुरुआत थी।
21

-1

कई जाँच किए गए अपवादों को फेंकने से समझ में आता है जब कई उचित चीजें करनी हैं।

उदाहरण के लिए हम कहते हैं कि आपके पास विधि है

public void doSomething(Credentials cred, Work work) 
    throws CredentialsRequiredException, TryAgainLaterException{...}

यह पेन अपवाद नियम का उल्लंघन करता है, लेकिन समझ में आता है।

Unfortunatelly, usuallly क्या होता है जैसे तरीके हैं

void doSomething() 
    throws IOException, JAXBException,SQLException,MyException {...}

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

इसलिए अधिकांश एक अपवाद अपवाद पर शासन करें।

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

सिडेनोट: कुछ वास्तव में लगभग हर जगह गलत हो सकता है, इसलिए कोई भी उपयोग करने के बारे में सोच सकता है? RuntimeException का विस्तार करता है, लेकिन "हम सभी गलतियाँ करते हैं" और "यह बाहरी व्यवस्था पर बात करता है और कभी-कभी नीचे होगा, इससे निपटें" के बीच अंतर है।


1
"कई उचित बातें करने के लिए" शायद ही कभी srp के साथ पालन - इस बिंदु से पहले जवाब
gnat

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