एक कोशिश अंत में (पकड़ने के बिना) बनाम एनुम-राज्य सत्यापन का उपयोग करना


9

मैं इस सवाल पर सलाह पढ़ रहा हूं कि एक अपवाद को कैसे निपटाया जाना चाहिए, जहां यह संभव हो सके।

सबसे अच्छा अभ्यास पर मेरे दुविधा है कि क्या एक आज़माएं / कैच का उपयोग करना चाहिए / अंत में एक enum वापस जाने के लिए है (या एक पूर्णांक है कि एक मूल्य का प्रतिनिधित्व करता है, त्रुटि के लिए, ठीक है, 2 के लिए आदि चेतावनी, मामले के आधार पर के लिए 0 1) इतना है कि एक उत्तर हमेशा क्रम में होता है, या किसी को अपवाद के माध्यम से जाने देना चाहिए ताकि कॉलिंग हिस्सा इससे निपट सके?

मैं जो इकट्ठा कर सकता हूं, यह मामले के आधार पर भिन्न हो सकता है, इसलिए मूल सलाह अजीब लगती है।

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

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

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

फिर से, http प्राप्त / पोस्ट उदाहरण के साथ, सवाल यह है कि क्या आपको एक नया ऑब्जेक्ट प्रदान करना चाहिए जो बताता है कि मूल कॉलर का क्या हुआ? यदि यह सहायक आपके द्वारा उपयोग किए जा रहे पुस्तकालय में था, तो क्या आप इसे ऑपरेशन के लिए एक स्थिति कोड प्रदान करने की अपेक्षा करेंगे, या क्या आप इसे एक कोशिश-पकड़ ब्लॉक में शामिल करेंगे? यदि आप इसे डिजाइन कर रहे हैं , तो क्या आप एक स्थिति कोड प्रदान करेंगे या एक अपवाद फेंक देंगे और ऊपरी स्तर को इसके बजाय एक स्थिति कोड / संदेश में अनुवाद करने देंगे?

सिनॉप्सिस: यदि आप एक अपवाद का उत्पादन करने के बजाय कोड का एक टुकड़ा कैसे चुनते हैं, तो किसी भी परिणाम के साथ एक स्थिति कोड देता है?


1
यह उस त्रुटि से नहीं निपट रहा है जो उपयोग किए जा रहे त्रुटि हैंडलिंग के रूप को बदल रही है। 404 के मामले में आप इसे पारित करने देंगे क्योंकि आप इसे संभाल नहीं पा रहे हैं।
स्टोनमेटल

"एक इंट जो एक मान का प्रतिनिधित्व करता है, 0 त्रुटि के लिए, 1 ठीक के लिए, 2 चेतावनी के लिए आदि" कृपया कहें कि यह एक ऑफ-द-कफ उदाहरण था! 0 का मतलब ओके का उपयोग करना निश्चित रूप से मानक है ...
एनाक्सीमेंडर

जवाबों:


15

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

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

प्रोग्राम लॉजिक को लागू करने के लिए अपवादों का उपयोग कभी नहीं किया जाना चाहिए। दूसरे शब्दों में, कुछ करने के लिए एक अपवाद न फेंकें; यह बताने के लिए कि यह नहीं किया जा सकता है एक अपवाद फेंकें।


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

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

1
+1: उचित और संतुलित स्पष्टीकरण के लिए। असाधारण मामलों को संभालने के लिए एक अपवाद का उपयोग किया जाना चाहिए। अन्यथा, एक फ़ंक्शन या विधि को एक सार्थक मान (एनम या विकल्प प्रकार) वापस करना चाहिए और कॉलर को इसे ठीक से संभालना चाहिए। शायद कोई तीसरे विकल्प का उल्लेख कर सकता है जो कार्यात्मक प्रोग्रामिंग में लोकप्रिय है, अर्थात निरंतरता।
जियोर्जियो

4

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

उदाहरण के लिए, System.IO.File.OpenRead () एक FileNotFoundException को फेंक देगा यदि आपूर्ति की गई फ़ाइल मौजूद नहीं है, हालांकि यह एक .Exists () विधि प्रदान करता है जो एक बूलियन मान देता है जो बताता है कि क्या फ़ाइल मौजूद है जिसे आपको पहले कॉल करना चाहिए। किसी भी अप्रत्याशित अपवाद से बचने के लिए OpenRead () को कॉल करना।

सवाल का हिस्सा "मुझे कब एक अपवाद से निपटना चाहिए" का जवाब देने के लिए, मैं कहूंगा कि आप वास्तव में इसके बारे में कुछ भी कर सकते हैं। यदि आपका तरीका किसी कॉल द्वारा बताई गई विधि द्वारा फेंके गए अपवाद से नहीं निपट सकता है, तो उसे न पकड़ें। इसे कॉल चेन को कुछ ऐसी चीज़ों से ऊपर उठाने दें जो इससे निपट सकें। कुछ मामलों में, यह सिर्फ एक लकड़हारा हो सकता है जो Application.UnhandledException को सुनता है।


बहुत से लोग, विशेष रूप से अजगर प्रोग्रामर, ईएएफपी को पसंद करते हैं, अर्थात "अनुमति प्राप्त करने की तुलना में क्षमा माँगना अधिक आसान है"
मार्क बूथ

1
अपवाद के साथ अपवाद से बचने के बारे में टिप्पणी के लिए +1 .Exists ()।
कोडिंगआउटलाउड

+1 यह अभी भी अच्छी सलाह है। कोड में मैं लिखता / प्रबंधित करता हूं, एक अपवाद "असाधारण" है, 9/10 बार एक अपवाद एक डेवलपर को देखने के लिए अभिप्रेत है, यह कहता है कि हे, आपको डिफेंसिवली प्रोग्रामिंग होना चाहिए! अन्य 1 समय, यह कुछ ऐसा है जिससे हम निपट नहीं सकते हैं, और हम इसे लॉग इन करते हैं, और सबसे अच्छा के रूप में बाहर निकल सकते हैं। संगतता महत्वपूर्ण है, उदाहरण के लिए, कन्वेंशन द्वारा हम सामान्य रूप से एक गलत झूठी प्रतिक्रिया, और मानक किराया / प्रसंस्करण के लिए आंतरिक संदेश देंगे। 3 पार्टी आपी का ऐसा लगता है कि हर चीज के लिए अपवाद को फेंक दिया जा सकता है, कॉल पर नियंत्रित किया जा सकता है, और मानक सहमत प्रक्रिया का उपयोग करके वापस आ सकता है।
गैविन हॉवेन

3

एक एनुम (या एक इंट्यू जो मान का प्रतिनिधित्व करता है, 0 को त्रुटि के लिए, 1 के लिए ठीक है, 2 के लिए चेतावनी, आदि, मामले पर निर्भर करता है) वापस करने के लिए एक कोशिश / पकड़ / अंत का उपयोग करें ताकि एक उत्तर हमेशा क्रम में हो,

यह एक भयानक डिजाइन है। सांख्यिक कोड में अनुवाद करके "मास्क" एक अपवाद नहीं है। इसे एक उचित, अस्पष्ट अपवाद के रूप में छोड़ दें।

या किसी को अपवाद के माध्यम से जाने देना चाहिए ताकि कॉलिंग हिस्सा इससे निपट सके?

यही अपवाद हैं।

जहां संभव हो, वहां इसे उठाया जाता है

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


यह एक भयानक डिजाइन नहीं है। Microsoft इसे कई स्थानों पर लागू करता है, अर्थात् डिफ़ॉल्ट asp.NET सदस्यता प्रदाता पर। इसके अलावा मैं यह नहीं देख सकता कि यह जवाब बातचीत में कुछ भी कैसे योगदान देता है
मिहलिस बागोस

@ मिहलिसबागोस: सभी मैं यह सुझाव दे सकता हूं कि प्रत्येक प्रोग्रामिंग भाषा द्वारा Microsoft के दृष्टिकोण को गले नहीं लगाया जाता है। अपवादों के बिना भाषाओं में, एक मूल्य वापस करना आवश्यक है। C सबसे उल्लेखनीय उदाहरण है। अपवाद वाली भाषाओं में, त्रुटियों को इंगित करने के लिए "कोड मान" वापस करना एक भयानक डिजाइन है। यह (कभी if-कभी) सरल अपवाद हैंडलिंग के बजाय (कभी-कभी) बोझिल बयान की ओर जाता है । उत्तर ("आप कैसे चुनें ...") सरल है। नहीं है । मुझे लगता है कि यह कहना बातचीत में जोड़ता है। हालाँकि आप इस उत्तर को अनदेखा करने के लिए स्वतंत्र हैं।
S.Lott

मैं यह नहीं कह रहा हूं कि आपकी राय नहीं है, लेकिन मैं कह रहा हूं कि आपकी राय विकसित नहीं है। उस टिप्पणी के साथ, मैं इसे तर्क के साथ लेता हूं कि हम अपवादों का उपयोग कहां कर सकते हैं, हमें, सिर्फ इसलिए कि हम कर सकते हैं? मैं कोड प्रवाह मामलों के वर्गीकरण / संगठन के बजाय मास्किंग के रूप में स्थिति कोड को नहीं देखता
Mihalis Bagos

1
अपवाद पहले से ही एक श्रेणीकरण / संगठन है। मुझे एक वापसी मूल्य के साथ एक अस्पष्ट अपवाद को प्रतिस्थापित करने का मूल्य नहीं दिखता है जो आसानी से "सामान्य" या "गैर-असाधारण" रिटर्न मूल्यों के साथ भ्रमित हो सकता है। रिटर्न मान हमेशा गैर-असाधारण होना चाहिए । मेरी राय बहुत विकसित नहीं है: यह बहुत सरल है। किसी संख्यात्मक कोड में अपवाद को रूपांतरित न करें। यह पहले से ही एक पूरी तरह से अच्छा डेटा ऑब्जेक्ट था जो सभी पूरी तरह से अच्छे उपयोग के मामलों में कार्य करता है जिसकी हम कल्पना कर सकते हैं।
S.Lott

3

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

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

वास्तव में कोई कठिन और तेज़ नियम नहीं है कि अपवाद को कब और कैसे निपटाना है, जब तक कि आप उनके साथ क्या करना है, जब तक आप उन्हें छोड़ दें।


1

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

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

त्रुटि कोड को प्रबंधित करना बहुत मुश्किल हो सकता है। आप आमतौर पर अपने कोड में बहुत सारे अनावश्यक दोहराव के साथ समाप्त होते हैं, और / या त्रुटि वाले राज्यों से निपटने के लिए बहुत सारे गंदे तर्क। एक उपयोगकर्ता होना और एक त्रुटि कोड का सामना करना और भी बदतर है, क्योंकि कोड स्वयं अर्थपूर्ण नहीं होगा, और उपयोगकर्ता को त्रुटि के लिए एक संदर्भ प्रदान नहीं करेगा। दूसरी ओर एक अपवाद उपयोगकर्ता को कुछ उपयोगी बता सकता है, जैसे "आप एक मूल्य दर्ज करना भूल गए", या "आपने एक अमान्य मान दर्ज किया है, यहां वह मान्य श्रेणी है जिसका आप उपयोग कर सकते हैं ...", या "मैं नहीं जानिए क्या हुआ, टेक सपोर्ट से संपर्क करें और उन्हें बताएं कि मैं बस दुर्घटनाग्रस्त हो गया, और उन्हें निम्नलिखित स्टैक ट्रेस दे ... "।

इसलिए ओपी के लिए मेरा सवाल यह है कि पृथ्वी पर आप त्रुटि कोड को छोड़कर अपवादों का उपयोग क्यों नहीं करना चाहेंगे?


0

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

यह एक अच्छे नियम को ध्यान में रखकर आता है:

कोड की लाइनें स्वर्ण गोलियों की तरह हैं। आप काम पूरा करने के लिए जितना संभव हो उतना कम उपयोग करना चाहते हैं।


0

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

मैंने यह भी फायदा उठाया कि अपवाद फेंकने से निष्पादन बंद हो जाएगा क्योंकि मैं नहीं चाहता कि डेटा अमान्य होने पर निष्पादन जारी रहे।

उदाहरण के लिए

procedure Validate(var R:TValidationRecord);
begin
  if Field1 is not valid then
  begin
    R.Field1ErrorCode=SomeErrorCode;
    ErrorFlag := True; 
  end; 
  if Field2 is not valid then
  begin
    R.Field2ErrorCode=SomeErrorCode;
    ErrorFlag := True; 
  end;
  if Field3 is not valid then
  begin
    R.Field3ErrorCode=SomeErrorCode;
    ErrorFlag := True; 
  end;

  if ErrorFlag then
    ThrowException
end;

यदि केवल बूलियन पर भरोसा करते हैं, तो मेरे फ़ंक्शन का उपयोग करने वाले डेवलपर को इसे खाते में लिखना चाहिए:

if not Validate() then
  DoNotContinue();

लेकिन वह भूल गया और केवल कॉल कर सकता है Validate()(मुझे पता है कि उसे नहीं करना चाहिए, लेकिन शायद वह हो सकता है)।

इसलिए, ऊपर दिए गए कोड में मुझे दो फायदे मिले:

  1. सत्यापन समारोह में केवल एक अपवाद।
  2. अपवाद, यहां तक ​​कि अनकैप्ड, निष्पादन को रोक देगा, और परीक्षण के समय दिखाई देगा

0

यहाँ एक जवाब नहीं है - तरह तरह के HttpException का एक प्रकार नहीं है।

यह एक बहुत मायने रखता है कि अंतर्निहित HTTP लाइब्रेरी 4xx या 5xx प्रतिक्रिया मिलने पर अपवाद को फेंक देते हैं; पिछली बार मैंने HTTP विनिर्देशों को देखा था जो त्रुटियां थीं।

जैसा कि उस अपवाद को फेंकने के लिए - या इसे लपेटकर और पुनर्विचार करके - मुझे लगता है कि वास्तव में उपयोग के मामले का सवाल है। उदाहरण के लिए, यदि आप एपीआई से कुछ डेटा हड़पने के लिए एक आवरण लिख रहे हैं और इसे उन अनुप्रयोगों के लिए उजागर कर सकते हैं जो आप तय कर सकते हैं कि गैर-मौजूद संसाधन के लिए एक HTTP 404 रिटर्न देने वाला एक अनुरोध उस को पकड़ने और वापस लौटने के लिए अधिक समझ में आता है। दूसरी ओर एक 406 त्रुटि (स्वीकार्य नहीं) एक त्रुटि को फेंकने के लायक हो सकती है क्योंकि इसका मतलब है कि कुछ बदल गया है और ऐप को दुर्घटनाग्रस्त हो जाना चाहिए और मदद के लिए जल रहा है और चिल्ला रहा है।

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