एक अमूर्त लीक एक अपवाद को पुनर्जीवित कर रहा है?


12

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

// in the interface

/**
 * @return This method returns a doohickey to use when you need to foo
 * @throws DoohickeyDisasterException
 */
public function getThatDoohickey();

// in the implementation

public function getThatDoohickey() {

    try {
        $SomethingInTheClass->doSomethingThatThrowsAnException();
    } catch (Exception $Exc) {
        throw new DoohickeyDisasterException('Message about doohickey failure');
    }

    // other code may return the doohickey

}

मैं इस पद्धति का उपयोग कर रहा हूं ताकि अमूर्तता को लीक होने से रोका जा सके।

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

बस स्पष्ट करने के लिए, मेरे प्रश्न में कोड की निम्न पंक्ति को बदलना शामिल होगा

throw new DoohickeyDisasterException($Exc->getMessage(), null, $Exc);

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

जवाबों:


11

मेरे सवाल हैं: क्या पिछले अपवाद को अमूर्त रूप से लीक करने के रूप में फेंके गए आंतरिक अपवाद को पारित किया जाएगा? यदि नहीं, तो क्या यह पिछले अपवाद के संदेश का पुन: उपयोग करने के लिए उपयुक्त होगा?

उत्तर है, यह निर्भर करता है"।

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

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

अक्सर, हालांकि, केवल अपवाद को लागू करने की अनुमति देना कार्यान्वयन का एक बहुत ही उचित विकल्प है, और अमूर्तता की समस्या नहीं है। बस पूछें "क्या मैं इसे फेंक दूंगा अगर मैं जो कोड कह रहा हूं वह नहीं था?"


8

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

परंतु।

इसके खिलाफ कुछ महत्वपूर्ण तर्क दिए जा सकते हैं । सबसे एहम:

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

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


6

सबसे पहले, आप यहाँ क्या कर रहे हैं एक अपवाद को पुनर्विचार नहीं कर रहा है। रीथ्रोइंग का शाब्दिक अर्थ इस तरह के अपवाद को फेंकना होगा:

try {
    $SomethingInTheClass->doSomethingThatThrowsAnException();
} catch (Exception $Exc) {
    throw $Exc;
}

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

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

लेकिन यह टपका हुआ सार नहीं है, यह एक और मुद्दा है।

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

उदाहरण के लिए, अगर DoohickeyDisasterException फ्रेमवर्क से एक वर्ग है और आपका कॉलिंग कोड इस तरह दिखता है, तो आपके पास एक टपका हुआ अमूर्त है:

try {
    $wrapper->getThatDoohickey();
} catch (DoohickeyDisasterException $Exc) {
    echo "The Doohickey is all wrong!";
    echo $Exc->getMessage();
    gotoAHappyPlaceAndSingHappySongs();
}

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

यदि, दूसरी ओर, DoohickeyDisasterException आपके खुद के बनाने में से एक है, तो आप अमूर्त रिसाव नहीं कर रहे हैं, आपको अपने पहले बिंदु के साथ खुद को और अधिक चिंता करनी चाहिए।


2

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

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.