क्या अपवाद के रूप में नियंत्रण प्रवाह को एक गंभीर एंटीपार्टर्न माना जाता है? यदि हां, तो क्यों?


129

90 के दशक के उत्तरार्ध में मैंने एक कोड बेस के साथ काफी काम किया जो प्रवाह नियंत्रण के रूप में अपवादों का उपयोग करता था। इसने टेलीफोनी अनुप्रयोगों को चलाने के लिए एक परिमित राज्य मशीन को लागू किया। हाल ही में मुझे उन दिनों की याद दिलाई गई है क्योंकि मैं एमवीसी वेब ऐप कर रहा हूं।

वे दोनों Controllerयह तय कर चुके हैं कि आगे कहाँ जाना है और गंतव्य तर्क को डेटा की आपूर्ति करना है। DTMF टोन जैसे पुराने स्कूल के टेलीफ़ोन के उपयोगकर्ता कार्य, क्रिया विधियों के पैरामीटर बन गए, लेकिन कुछ की तरह वापस करने के बजाय ViewResult, उन्होंने a फेंक दिया StateTransitionException

मुझे लगता है कि मुख्य अंतर यह था कि कार्रवाई के तरीके voidकार्य थे । मुझे इस तथ्य के साथ सभी चीजें याद नहीं हैं, लेकिन मुझे यह याद करने में भी संकोच हो रहा है कि बहुत याद करने की राह पर नहीं जा सकते क्योंकि उस नौकरी के बाद से, जैसे कि 15 साल पहले, मैंने इसे किसी अन्य नौकरी में उत्पादन कोड में कभी नहीं देखा था । मैंने माना कि यह एक संकेत था कि यह एक तथाकथित विरोधी पैटर्न था।

क्या यह मामला है, और यदि हां, तो क्यों?

अद्यतन: जब मैंने प्रश्न पूछा, तो मेरे पास पहले से ही @ MasonWheeler का जवाब था, इसलिए मैं उस उत्तर के साथ गया जिसने मेरे ज्ञान को सबसे अधिक जोड़ा। मुझे लगता है कि उनका एक अच्छा जवाब है।



25
पायथन में, नियंत्रण प्रवाह के रूप में अपवादों का उपयोग करना "पायथोनिक" माना जाता है।
user16764

4
अगर मैं ऐसा काम करता तो मैं जावा, मैं निश्चित रूप से इसके लिए एक अपवाद नहीं फेंकता। मैं कुछ गैर-अपवाद, गैर-त्रुटि, फेंकने योग्य पदानुक्रम से प्राप्त करूंगा।
थॉमस एडिंग

2
मौजूदा उत्तरों में जोड़ने के लिए, यहां एक छोटी दिशानिर्देश है जिसने मुझे अच्छी तरह से सेवा दी है: - "खुशहाल पथ" के लिए कभी भी अपवाद का उपयोग न करें। खुश रास्ता दोनों (वेब ​​के लिए) संपूर्ण अनुरोध, या बस एक वस्तु / विधि हो सकता है। अन्य सभी समझदार नियम अभी भी लागू होते हैं, निश्चित रूप से :)
होउन

8
अपवाद हमेशा एक आवेदन के प्रवाह को नियंत्रित नहीं कर रहे हैं?

जवाबों:


109

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

क्यों, आम तौर पर, के लिए एक त्वरित सारांश के रूप में, यह एक विरोधी पैटर्न है:

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

अधिक जानकारी के लिए वार्ड की विकि पर चर्चा पढ़ें।


इस प्रश्न का एक डुप्लिकेट यहाँ भी देखें


18
आपका उत्तर यह ध्वनि करता है, हालांकि अपवाद सभी परिस्थितियों के लिए खराब हैं , जबकि प्रवाह नियंत्रण के रूप में अपवाद पर केंद्रित है।
whatsisname

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

24
@BillK, तब तर्क देता है, और इस बात के बारे में सरलीकृत बयान नहीं देते हैं कि अपवाद कैसे हैं।
विंस्टन इर्वर्ट

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

12
@ मट्टनज़: ifऔर foreachपरिष्कृत GOTOएस भी हैं । सच कहूँ, मुझे लगता है कि गोटो के साथ तुलना सहायक नहीं है; यह लगभग एक अपमानजनक शब्द की तरह है। GOTO का उपयोग आंतरिक रूप से बुराई नहीं है - इसमें वास्तविक समस्याएं हैं, और अपवाद उन लोगों को साझा कर सकते हैं, लेकिन वे नहीं कर सकते। उन समस्याओं को सुनने के लिए यह अधिक उपयोगी होगा।
Eamon Nerbonne

110

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

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

यदि आप इन दो कारणों में से एक के लिए अपवादों का उपयोग नहीं कर रहे हैं, तो संभवतः ऐसा करने का एक बेहतर तरीका है।


18
हालांकि इस सवाल का जवाब नहीं है। उनके लिए जो डिजाइन किया गया था वह अप्रासंगिक है; केवल एक चीज जो प्रासंगिक है वह यह है कि नियंत्रण प्रवाह के लिए उनका उपयोग करना बुरा है जो एक ऐसा विषय है जिसे आपने नहीं छुआ। एक उदाहरण के रूप में, C ++ टेम्प्लेट एक चीज़ के लिए डिज़ाइन किए गए थे, लेकिन मेटाप्रोग्रामिंग के लिए उपयोग किए जाने के लिए पूरी तरह से ठीक हैं, एक ऐसा डिज़ाइन जिसे डिज़ाइनरों ने कभी अनुमान नहीं लगाया था।
थॉमस बोनिनी

6
@ क्रेप: डिजाइनरों ने कभी बहुत सी चीजों का अनुमान नहीं लगाया, जैसे दुर्घटना से ट्यूरिंग-पूर्ण टेम्पलेट प्रणाली के साथ समाप्त होना! C ++ टेम्प्लेट यहां उपयोग करने के लिए शायद ही एक अच्छा उदाहरण है।
मेसन व्हीलर

15
@Krelp - C ++ टेम्प्लेट मेटाप्रोग्रामिंग के लिए 'बिल्कुल ठीक' नहीं हैं। वे एक दुःस्वप्न हैं जब तक कि आप उन्हें सही नहीं पाते हैं, और तब वे केवल-कोड की ओर लिखते हैं यदि आप टेम्पलेट-जीनियस नहीं हैं। आप एक बेहतर उदाहरण चुन सकते हैं।
माइकल कोहेन

अपवाद विशेष रूप से फ़ंक्शन संरचना को नुकसान पहुंचाते हैं, और सामान्य रूप से कोड संक्षिप्तता। उदाहरण के लिए, जब मैं अनुभवहीन था, तो मैंने एक परियोजना में एक अपवाद का उपयोग किया था, और यह लंबे समय तक परेशानी का कारण बना, क्योंकि 1) लोगों को इसे पकड़ने के लिए याद रखना होगा, 2) आप नहीं लिख सकते const myvar = theFunctionक्योंकि myvar को try-catch से बाहर बनाया जाना है, इस प्रकार यह अधिक स्थिर नहीं है। इसका मतलब यह नहीं है कि मैं इसे C # में उपयोग नहीं करता हूं क्योंकि यह जो भी कारण है वहां एक मुख्यधारा है, लेकिन मैं उन्हें कम करने की कोशिश कर रहा हूं।
हाय-एंजेल

2
@AndreasBonini क्या वे डिजाइन किए गए हैं / मामलों के लिए इरादा है क्योंकि अक्सर कंपाइलर / फ्रेमवर्क / रनटाइम कार्यान्वयन निर्णयों के परिणामस्वरूप डिजाइन के साथ गठबंधन किया जाता है। उदाहरण के लिए, एक अपवाद को फेंकना एक साधारण रिटर्न की तुलना में बहुत अधिक "महंगा" हो सकता है क्योंकि यह किसी को कोड को डीबग करने में मदद करने के लिए जानकारी इकट्ठा करता है जैसे कि स्टैक के निशान, आदि
binki

29

अपवाद निरंतरता के रूप में शक्तिशाली हैं और GOTO। वे एक सार्वभौमिक नियंत्रण प्रवाह निर्माण हैं।

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

Microsoft वोल्टा परियोजना एक (अब बंद) अनुसंधान परियोजना है जो जावास्क्रिप्ट में मनमाने ढंग से .NET कोड संकलित करने के लिए है। .NET के अपवाद हैं जिनके शब्दार्थ जावास्क्रिप्ट के लिए बिल्कुल मैप नहीं करते हैं, लेकिन इससे भी महत्वपूर्ण बात यह है कि इसमें थ्रेड्स हैं , और आपको किसी भी तरह जावास्क्रिप्ट पर मैप करना होगा। Volta ने जावास्क्रिप्ट अपवादों का उपयोग करके Volta Continuations को लागू करके ऐसा किया और फिर Volta Continuations के संदर्भ में सभी .NET नियंत्रण प्रवाह निर्माणों को लागू करें। उन्हें अपवाद का उपयोग नियंत्रण प्रवाह के रूप में करना था , क्योंकि कोई अन्य नियंत्रण प्रवाह पर्याप्त शक्तिशाली नहीं है।

आपने स्टेट मशीनों का उल्लेख किया। एसएम उचित पूंछ कॉल के साथ लागू करने के लिए तुच्छ हैं: प्रत्येक राज्य एक सबरूटीन है, हर राज्य संक्रमण एक सबरूट कॉल है। SM को आसानी से GOTOया Coroutines या Continuations के साथ लागू किया जा सकता है । हालांकि, जावा उन चार में से किसी की जरूरत नहीं है, लेकिन यह करता है अपवाद है। तो, यह नियंत्रण प्रवाह के रूप में उपयोग करने के लिए पूरी तरह से स्वीकार्य है। (ठीक है, वास्तव में, सही विकल्प संभवतः उचित नियंत्रण प्रवाह निर्माण के साथ एक भाषा का उपयोग करना होगा, लेकिन कभी-कभी आप जावा से अटक सकते हैं।)


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

20
@ ErikReppen: मुझे एहसास है कि आप सिर्फ व्यंग्यात्मक हैं, लेकिन। । । मैं वास्तव में इस तथ्य को नहीं समझता कि हम "जावास्क्रिप्ट के साथ क्लाइंट-साइड वेब डेवलपमेंट पर हावी हैं" का भाषा की सुविधाओं के साथ कुछ भी नहीं है। इसका उस बाजार में एकाधिकार है, इसलिए बहुत सारी समस्याओं को दूर करने में सक्षम है जिन्हें व्यंग्य के साथ नहीं लिखा जा सकता है।
मारख

1
टेल रीसर्शन एक अच्छा बोनस होता (वे भविष्य में होने वाले फंक्शन फीचर्स को दर्शाते हैं), लेकिन हां, मैं कहूंगा कि यह वीबी, फ्लैश, ऐप्पल आदि के खिलाफ है ... फीचर से संबंधित कारणों से। यदि यह जटिलता को कम नहीं करता है और सामान्य रूप से इसे कम करता है, तो यह कुछ बिंदु पर वास्तविक प्रतियोगिता होती। मैं वर्तमान में Node.js चला रहा हूं कि एक गुप्त सी # + जावा स्टैक के लिए 21 कॉन्फिग फाइलों का पुनर्लेखन करने के लिए और मुझे पता है कि मैं ऐसा करने वाला अकेला नहीं हूं। यह बहुत अच्छा है जो इसमें अच्छा है।
एरिक रेपेन

1
कई भाषाओं में न तो गोटो हैं (गोटो को हानिकारक माना जाता है!), कोरटाइन या निरंतरता और पूरी तरह से वैध प्रवाह नियंत्रण को लागू करने के लिए बस ifs, whiles और function call (या gosubs!) का उपयोग करते हैं। इनमें से अधिकांश वास्तव में एक दूसरे का अनुकरण करने के लिए इस्तेमाल किया जा सकता है, जिस तरह एक निरंतरता उपरोक्त सभी का प्रतिनिधित्व करने के लिए इस्तेमाल किया जा सकता है। (उदाहरण के लिए, आप एक का उपयोग करने के लिए थोड़ी देर का उपयोग कर सकते हैं, भले ही कोड के लिए एक बदबूदार तरीका)। इसलिए उन्नत प्रवाह नियंत्रण करने के लिए कोई अपवाद आवश्यक नहीं है।
Shayne

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

19

जैसा कि दूसरों ने कई उल्लेख किया है, ( उदाहरण के लिए इस स्टैक ओवरफ्लो प्रश्न में ), कम से कम विस्मय का सिद्धांत यह मना करेगा कि आप केवल नियंत्रण प्रवाह के लिए अपवादों का अत्यधिक उपयोग करते हैं। दूसरी ओर, कोई भी नियम 100% सही नहीं है, और हमेशा ऐसे मामले होते हैं जहां एक अपवाद "सिर्फ सही उपकरण" है - बहुत कुछ gotoअपने आप से, वैसे, जो जावा के रूप में breakऔर continueभाषाओं में जहाजों के रूप में , जो अक्सर भारी नेस्टेड छोरों से बाहर निकलने का सही तरीका है, जो हमेशा बचने योग्य नहीं होते हैं।

निम्नलिखित ब्लॉग पोस्ट एक गैर-स्थानीय के लिए एक बल्कि जटिल बल्कि बल्कि दिलचस्प उपयोग-मामले की व्याख्या करता है ControlFlowException:

यह बताता है कि कैसे jOOQ के अंदर (जावा के लिए एक SQL एब्स्ट्रैक्शन लाइब्रेरी) (अस्वीकरण: मैं विक्रेता के लिए काम करता हूं), ऐसे अपवाद कभी-कभी SQL रेंडरिंग प्रक्रिया को जल्दी खत्म करने के लिए उपयोग किया जाता है जब कुछ "दुर्लभ" स्थिति मिलती है।

ऐसी स्थितियों के उदाहरण हैं:

  • बहुत सारे बंधे मूल्यों का सामना करना पड़ता है। कुछ डेटाबेस अपने SQL स्टेटमेंट्स (SQLite: 999, Ingres 10.1.0: 1024, Sybase ASE 15.5: 2000, SQL Server 2008: 2100) में बाइंड मानों की मनमानी संख्या का समर्थन नहीं करते हैं। उन मामलों में, jOOQ SQL रेंडरिंग चरण को समाप्त कर देता है और इनबिल्ड बाइंड मानों के साथ SQL स्टेटमेंट को फिर से प्रस्तुत करता है। उदाहरण:

    // Pseudo-code attaching a "handler" that will
    // abort query rendering once the maximum number
    // of bind values was exceeded:
    context.attachBindValueCounter();
    String sql;
    try {
    
      // In most cases, this will succeed:
      sql = query.render();
    }
    catch (ReRenderWithInlinedVariables e) {
      sql = query.renderWithInlinedBindValues();
    }

    यदि हमने स्पष्ट रूप से हर बार उन्हें गिनने के लिए क्वेरी एएसटी से बाइंड मानों को स्पष्ट रूप से निकाला है, तो हम उन 99.9% प्रश्नों के लिए मूल्यवान सीपीयू चक्र बर्बाद कर देंगे जो इस समस्या से ग्रस्त नहीं हैं।

  • कुछ तर्क केवल एक एपीआई के माध्यम से अप्रत्यक्ष रूप से उपलब्ध हैं जिन्हें हम केवल "आंशिक रूप से" निष्पादित करना चाहते हैं। UpdatableRecord.store()विधि एक उत्पन्न करता है INSERTया UPDATEबयान के आधार पर Recordकी आंतरिक झंडे। "बाहर" से, हम नहीं जानते कि किस प्रकार का तर्क निहित है store()(जैसे आशावादी लॉकिंग, ईवेंट श्रोता हैंडलिंग, आदि) इसलिए हम उस तर्क को दोहराना नहीं चाहते हैं जब हम एक बैच स्टेटमेंट में कई रिकॉर्ड संग्रहीत करते हैं, जहां हम store()केवल SQL स्टेटमेंट जेनरेट करना चाहते हैं , वास्तव में इसे निष्पादित नहीं करते हैं। उदाहरण:

    // Pseudo-code attaching a "handler" that will
    // prevent query execution and throw exceptions
    // instead:
    context.attachQueryCollector();
    
    // Collect the SQL for every store operation
    for (int i = 0; i < records.length; i++) {
      try {
        records[i].store();
      }
    
      // The attached handler will result in this
      // exception being thrown rather than actually
      // storing records to the database
      catch (QueryCollectorException e) {
    
        // The exception is thrown after the rendered
        // SQL statement is available
        queries.add(e.query());                
      }
    }

    अगर हमने store()तर्क को "पुनः प्रयोग करने योग्य" एपीआई में बदल दिया है जो कि एसक्यूएल को निष्पादित नहीं करने के लिए वैकल्पिक रूप से अनुकूलित किया जा सकता है , तो हम इसे बनाए रखने के लिए मुश्किल नहीं बल्कि मुश्किल से पुनः उपयोग करने योग्य एपीआई बनाने में देख रहे होंगे।

निष्कर्ष

संक्षेप में, इन गैर-स्थानीय gotoएस का हमारा उपयोग सिर्फ उनके जवाब में मेसन व्हीलर की बातों के साथ है :

"मुझे अभी इस स्थिति का सामना करना पड़ा है कि मैं इस बिंदु पर ठीक से व्यवहार नहीं कर सकता, क्योंकि मेरे पास इसे संभालने के लिए पर्याप्त संदर्भ नहीं है, लेकिन दिनचर्या ने मुझे बुलाया (या कॉल स्टैक को कुछ और) यह जानने के लिए कि इसे कैसे संभालना चाहिए। । "

दोनों ControlFlowExceptionsविकल्पों का उपयोग उनके विकल्पों की तुलना में लागू करना आसान था, जिससे हमें संबंधित आंतरिक लोगों से इसे हटाए बिना तर्क की एक विस्तृत श्रृंखला का पुन: उपयोग करने की अनुमति मिली।

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


11

नियंत्रण प्रवाह के लिए अपवादों का उपयोग करना आमतौर पर एक विरोधी पैटर्न माना जाता है, लेकिन अपवाद हैं (कोई भी उद्देश्य नहीं)।

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

अपने सॉफ्टवेयर में बग एक समारोह का कारण बनता है कि, अवैध तर्क के साथ कहा जा जैसे nullजहां नहीं की अनुमति देता है, है एक असाधारण हालत।

किसी ऐसी चीज के लिए अपवाद का उपयोग करके जो असाधारण नहीं है, आप जिस समस्या को हल करने का प्रयास कर रहे हैं, उसके लिए आप अनुचित सार का उपयोग कर रहे हैं।

लेकिन एक प्रदर्शन जुर्माना भी हो सकता है। कुछ भाषाओं में अधिक या कम कुशल अपवाद हैंडलिंग कार्यान्वयन है, इसलिए यदि आपकी पसंद की भाषा में कुशल अपवाद हैंडलिंग नहीं है, तो यह बहुत महंगा हो सकता है, प्रदर्शन-वार *।

लेकिन अन्य भाषाओं, उदाहरण के लिए रूबी, नियंत्रण प्रवाह के लिए एक अपवाद की तरह सिंटैक्स है। असाधारण परिस्थितियों को raise/ rescueऑपरेटरों द्वारा नियंत्रित किया जाता है । लेकिन आप उपयोग कर सकते हैं throw/ catchजैसे अपवाद नियंत्रण प्रवाह निर्माण **।

इसलिए, हालांकि अपवाद आमतौर पर नियंत्रण प्रवाह के लिए उपयोग नहीं किए जाते हैं , आपकी पसंद की भाषा में अन्य मुहावरे हो सकते हैं।

* अपवादों के प्रदर्शन के महंगे उपयोग का उदाहरण: मैं एक बार खराब प्रदर्शन करने वाले ASP.NET वेब फॉर्म एप्लिकेशन को ऑप्टिमाइज़ करने के लिए तैयार था। यह पता चला है, कि एक बड़ी तालिका का प्रतिपादन int.Parse()लगभग पुकार रहा था । एक औसत पृष्ठ पर एक हजार खाली तार, जिसके परिणामस्वरूप लगभग। एक हजार अपवादों को संभाला जा रहा है। कोड को बदलकर int.TryParse()मैंने एक सेकेंड मुंडाया! हर एक पेज रिक्वेस्ट के लिए!

** यह एक प्रोग्रामर के लिए रूबी के लिए अन्य भाषाओं से आने के लिए बहुत भ्रामक हो सकता है, क्योंकि दोनों throwऔर catchकई अन्य भाषाओं में अपवादों से जुड़े कीवर्ड हैं।


1
+1 के लिए "कुछ अपवादों के लिए अपवाद का उपयोग करके जो असाधारण नहीं है, आप समस्या को हल करने के लिए अनुचित सार का उपयोग कर रहे हैं।"
गियोर्जियो

8

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

status = getValue(&inout);
if (status < 0)
{
    logError("message");
    return status;
}

doSomething(*inout);

या आपकी भाषा के समकक्ष, जैसे कि त्रुटि की स्थिति के रूप में एक मान के साथ एक टपल लौटना, आदि। अक्सर ऐसे लोग जो बताते हैं कि "महंगा" अपवाद हैंडलिंग कैसे है, ifउपरोक्त सभी अतिरिक्त कथनों की उपेक्षा करें जैसे कि आपको जोड़ने की आवश्यकता है यदि आप डॉन ' टी अपवादों का उपयोग करें।

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

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


2
जब तक कि यदि कथन केवल 'असाधारण' परिस्थितियों पर विफल होते हैं, तो आधुनिक सीपीयू की शाखा भविष्यवाणी तर्क उनकी लागत को नगण्य बना देती है। यह एक ऐसी जगह है जहां मैक्रोज़ वास्तव में मदद कर सकते हैं, जब तक आप सावधान रहें और उनमें बहुत अधिक करने की कोशिश न करें।
जेम्स

5

पायथन में, अपवाद जनरेटर और पुनरावृत्ति समाप्ति के लिए उपयोग किए जाते हैं। पायथन में बहुत कुशल प्रयास हैं / ब्लॉकों को छोड़कर, लेकिन वास्तव में एक अपवाद को बढ़ाने से कुछ ओवरहेड होता है।

पायथन में मल्टी-लेवल ब्रेक या गोटो स्टेटमेंट की कमी के कारण, मेरे पास कई बार अपवाद हैं:

class GOTO(Exception):
  pass

try:
  # Do lots of stuff
  # in here with multiple exit points
  # each exit point does a "raise GOTO()"
except GOTO:
  pass
except Exception as e:
  #display error

6
यदि आपको एक गहरे नेस्टेड स्टेटमेंट में कहीं पर कैलकुलेशन को समाप्त करना है और कुछ कॉमन कंटिन्यूएशन कोड पर जाना है, तो निष्पादन के इस विशेष पथ को संभवतः एक फ़ंक्शन के रूप में फैक्टर आउट किया जा सकता है, जिसके returnस्थान पर goto
9000

3
@ 9000 मैं बिल्कुल एक ही तरह की टिप्पणी करने वाला था ... try:ब्लॉक को 1 या 2 लाइनों पर रखें कृपया, कभी नहीं try: # Do lots of stuff
विम

1
@ 9000, कुछ मामलों में, निश्चित है। लेकिन फिर आप स्थानीय चर तक पहुंच खो देते हैं, और आप अपने कोड को अभी तक एक और जगह ले जाते हैं, जब प्रक्रिया एक सुसंगत, रैखिक प्रक्रिया होती है।
गहुआ

4
@gahooa: मैं तुम्हारी तरह सोचता था। यह मेरे कोड की खराब संरचना का संकेत था। जब मैंने इसमें और अधिक विचार डाला, तो मैंने देखा कि स्थानीय संदर्भ कुछ मापदंडों, कोड की कुछ पंक्तियों और बहुत सटीक अर्थ के साथ छोटे कार्यों में किए गए पूरे गड़बड़ हो सकते हैं। मैंने कभी पीछे मुड़कर नहीं देखा।
9000

4

आइए इस तरह के अपवाद का उपयोग करें:

एल्गोरिथ्म कुछ मिलने तक पुनरावर्ती खोज करता है। इसलिए पुनरावृत्ति से वापस आने के लिए एक परिणाम के लिए जाँच की जा रही है, और फिर वापस लौटें, अन्यथा जारी रखें। और वह बार-बार कुछ पुनरावृत्ति गहराई से वापस आ रहा है।

अतिरिक्त बूलियन की आवश्यकता के अलावा found(एक वर्ग में पैक किया जाना है, जहां अन्यथा शायद केवल एक इंट वापस आ गया होगा), और पुनरावृत्ति की गहराई के लिए एक ही पश्चात होता है।

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


हम्म, क्या वास्तव में विपरीत स्थिति के लिए, या अपर्याप्त या कम तर्क के लिए डाउनवोटिंग है? मैं वास्तव में उत्सुक हूं।
जोप एगेगन

मैं बिल्कुल इस भविष्यवाणी का सामना कर रहा हूं, मैं उम्मीद कर रहा था कि आप देख सकते हैं कि आप मेरे निम्नलिखित प्रश्न के बारे में क्या सोचते हैं? रिकर्सिवली अपवाद का उपयोग कर कारण (संदेश) एक शीर्ष स्तर अपवाद के लिए जमा करने के लिए codereview.stackexchange.com/questions/107862/...
CL22

@Jodes मैंने अभी-अभी आपकी दिलचस्प तकनीक को पढ़ा है, लेकिन मैं अभी काफी व्यस्त हूँ। आशा है कि कोई और इस मुद्दे पर अपना प्रकाश डालेगा।
जोप एगेन

4

प्रोग्रामिंग काम के बारे में है

मुझे लगता है कि इसका उत्तर देने का सबसे आसान तरीका यह है कि ओओपी ने पिछले कुछ वर्षों में जो प्रगति की है, उसे समझना है। OOP में किया गया सब कुछ (और उस मामले के लिए सबसे प्रोग्रामिंग प्रतिमान), काम की जरूरत के आसपास मॉडलिंग की जाती है

हर बार एक विधि कहा जाता है, फोन करने वाला कह रहा है "मुझे नहीं पता कि यह काम कैसे करना है, लेकिन आप जानते हैं कि कैसे, इसलिए आप इसे मेरे लिए करते हैं।"

इसने एक कठिनाई पेश की: क्या होता है जब आम तौर पर कहा जाता है कि काम कैसे करना है, लेकिन हमेशा नहीं? हमें संवाद करने का एक तरीका चाहिए "मैं आपकी मदद करना चाहता था, मैंने वास्तव में किया था, लेकिन मैं ऐसा नहीं कर सकता।"

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

एक असाधारण सादृश्य

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

आप जो पसंद करेंगे उसे आपको बताना होगा, "देखो, मैं इसे ठीक नहीं कर सकता क्योंकि ऐसा लगता है जैसे आपका पंप काम नहीं कर रहा है।"

इस जानकारी के साथ, आप निष्कर्ष निकाल सकते हैं कि आप इलेक्ट्रीशियन को समस्या पर एक नज़र रखना चाहते हैं। शायद इलेक्ट्रीशियन को बढ़ई से संबंधित कुछ मिल जाएगा, और आपको बढ़ई को इसे ठीक करने की आवश्यकता होगी।

बिल्ली, आप शायद यह भी नहीं जानते होंगे कि आपको एक इलेक्ट्रीशियन की आवश्यकता है, आप नहीं जानते कि आपको किसकी ज़रूरत है। आप एक घर की मरम्मत के व्यवसाय में केवल मध्य-प्रबंधन कर रहे हैं, और आपका ध्यान नलसाजी है। तो आप बताएं कि आप समस्या के बारे में बॉस हैं, और फिर वह इसे ठीक करने के लिए इलेक्ट्रीशियन से कहता है।

यह वह है जो अपवाद मॉडलिंग कर रहे हैं: एक असफल फैशन में जटिल विफलता मोड। प्लंबर को इलेक्ट्रीशियन के बारे में जानने की आवश्यकता नहीं है- उसे यह जानने की भी आवश्यकता नहीं है कि कोई व्यक्ति चेन को समस्या को ठीक कर सकता है। वह सिर्फ उस समस्या पर रिपोर्ट करता है जो उसे सामना करना पड़ा।

तो ... एक विरोधी पैटर्न?

ठीक है, इसलिए अपवाद के बिंदु को समझना पहला कदम है। अगला यह समझना है कि एक विरोधी पैटर्न क्या है।

एक विरोधी पैटर्न के रूप में अर्हता प्राप्त करने के लिए, यह करने की आवश्यकता है

  • समस्या का समाधान
  • निश्चित रूप से नकारात्मक परिणाम हैं

पहला बिंदु आसानी से मिलता है- सिस्टम ने काम किया, है ना?

दूसरा बिंदु चिपचिपा है। सामान्य नियंत्रण प्रवाह के रूप में अपवादों का उपयोग करने का प्राथमिक कारण बुरा है क्योंकि यह उनका उद्देश्य नहीं है। किसी कार्यक्रम में कार्यक्षमता के किसी भी दिए गए टुकड़े का एक अपेक्षाकृत स्पष्ट उद्देश्य होना चाहिए, और उस उद्देश्य का सह-विरोध अनावश्यक भ्रम पैदा करता है।

लेकिन यह निश्चित नुकसान नहीं है। यह चीजों को करने के लिए एक खराब तरीका है, और अजीब है, लेकिन एक विरोधी पैटर्न है? नहीं, बस ... अजीब है।


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

"यह चीजों को करने का एक खराब तरीका है" - क्या यह एक विरोधी पैटर्न के रूप में वर्गीकृत करने के लिए पर्याप्त नहीं होना चाहिए?
है_फैक्टर

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