exception - अपवाद फेंकने के लिए कब?




language-agnostic (20)

मेरे पास प्रत्येक शर्त के लिए अपवाद हैं जो मेरे आवेदन की अपेक्षा नहीं करते हैं। UserNameNotValidException , PasswordNotCorrectException इत्यादि।

हालांकि मुझे बताया गया कि मुझे उन शर्तों के लिए अपवाद नहीं बनाना चाहिए। मेरे यूएमएल में वे मुख्य प्रवाह के अपवाद हैं, तो यह अपवाद क्यों नहीं होना चाहिए?

अपवाद बनाने के लिए कोई मार्गदर्शन या सर्वोत्तम प्रथाओं?


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


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

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


अपवाद कुछ हद तक महंगे प्रभाव हैं, उदाहरण के लिए यदि आपके पास एक उपयोगकर्ता है जो एक अवैध पासवर्ड प्रदान करता है, तो आमतौर पर विफलता ध्वज, या कुछ अन्य संकेतक को पास करने का एक बेहतर विचार है कि यह अमान्य है।

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


अपवाद फेंकने के लिए अंगूठे का नियम बहुत आसान है। आप ऐसा करते हैं जब आपका कोड एक अविश्वसनीय INVALID स्थिति में प्रवेश कर चुका है। यदि डेटा से समझौता किया गया है या आप उस बिंदु पर होने वाली प्रसंस्करण को वापस नहीं कर सकते हैं तो आपको इसे समाप्त करना होगा। वास्तव में आप और क्या कर सकते हैं? आपका प्रसंस्करण तर्क अंततः कहीं और विफल हो जाएगा। अगर आप किसी भी तरह से ठीक हो सकते हैं तो ऐसा करें और अपवाद फेंक न दें।

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


अपवाद वर्ग "सामान्य" कक्षाओं की तरह हैं। जब आप अलग-अलग फ़ील्ड और विभिन्न परिचालनों के साथ "अलग" ऑब्जेक्ट होते हैं तो आप एक नई कक्षा बनाते हैं।

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


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


आम तौर पर आप अपने आवेदन में होने वाली किसी भी चीज के लिए अपवाद फेंकना चाहते हैं जो "असाधारण" है

आपके उदाहरण में, उन दोनों अपवादों की तरह दिखता है कि आप उन्हें पासवर्ड / उपयोगकर्ता नाम सत्यापन के माध्यम से बुला रहे हैं। उस स्थिति में यह तर्क दिया जा सकता है कि यह वास्तव में असाधारण नहीं है कि कोई उपयोगकर्ता नाम / पासवर्ड गलत टाइप करेगा।

वे आपके यूएमएल के मुख्य प्रवाह के लिए "अपवाद" हैं लेकिन प्रसंस्करण में अधिक "शाखाएं" हैं।

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


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


मेरा व्यक्तिगत दिशानिर्देश है: वर्तमान कोड ब्लॉक की मौलिक धारणा झूठी पाया जाने पर एक अपवाद फेंक दिया जाता है।

उदाहरण 1: कहें कि मेरे पास एक ऐसा कार्य है जो मनमानी वर्ग की जांच कर रहा है और उस वर्ग को सूची <> से प्राप्त होने पर सत्य वापस आना चाहिए। यह कार्य सवाल पूछता है, "क्या यह वस्तु सूची का वंशज है?" इस समारोह को कभी अपवाद नहीं फेंकना चाहिए, क्योंकि इसके संचालन में कोई ग्रे क्षेत्र नहीं है - प्रत्येक वर्ग या तो सूची <> से प्राप्त नहीं होता है या नहीं, इसलिए उत्तर हमेशा "हाँ" या "नहीं" होता है।

उदाहरण 2: कहें कि मेरे पास एक और फ़ंक्शन है जो एक सूची <> की जांच करता है और यदि इसकी लंबाई 50 से अधिक है, और यदि लंबाई कम है तो गलत हो जाता है। यह फ़ंक्शन सवाल पूछता है, "क्या इस सूची में 50 से अधिक आइटम हैं?" लेकिन यह सवाल एक धारणा बनाता है - यह मानता है कि यह वस्तु एक सूची है। अगर मैं इसे एक नल सौंपता हूं, तो वह धारणा झूठी है। उस स्थिति में, यदि फ़ंक्शन या तो सत्य या गलत लौटाता है, तो यह अपने नियमों को तोड़ रहा है। फ़ंक्शन कुछ भी वापस नहीं कर सकता है और दावा करता है कि उसने सही तरीके से प्रश्न का उत्तर दिया है। तो यह वापस नहीं आता है - यह एक अपवाद फेंकता है।

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

इस समीकरण का दूसरा पक्ष यह है: यदि आप अपने कार्यों को अक्सर अपवाद फेंकते हैं, तो आपको शायद उनकी धारणाओं को परिशोधित करने की आवश्यकता है।


मेरे छोटे दिशानिर्देश महान पुस्तक "कोड पूर्ण" से काफी प्रभावित हैं:

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

मेरे पास तीन प्रकार की स्थितियां हैं जिन्हें मैं पकड़ता हूं।

  1. खराब या अनुपलब्ध इनपुट अपवाद नहीं होना चाहिए। पता लगाने, गुण सेट करने और संदेशों के साथ उसी पृष्ठ पर वापस अग्रेषित करने के लिए क्लाइंट साइड जेएस और सर्वर साइड रेगेक्स दोनों का उपयोग करें।

  2. AppException। यह आमतौर पर एक अपवाद है जिसे आप अपने कोड में पहचानते हैं और फेंक देते हैं। दूसरे शब्दों में ये वे हैं जिन्हें आप उम्मीद करते हैं (फ़ाइल मौजूद नहीं है)। इसे लॉग करें, संदेश सेट करें, और सामान्य त्रुटि पृष्ठ पर वापस अग्रेषित करें। इस पृष्ठ में आमतौर पर क्या हुआ इसके बारे में कुछ जानकारी है।

  3. अप्रत्याशित अपवाद। ये वे हैं जिन्हें आप नहीं जानते हैं। विवरण के साथ लॉग इन करें और उन्हें एक सामान्य त्रुटि पृष्ठ पर अग्रेषित करें।

उम्मीद है की यह मदद करेगा


मेरे लिए एक आवश्यक तकनीकी या व्यावसायिक नियम विफल होने पर अपवाद फेंक दिया जाना चाहिए। उदाहरण के लिए यदि कोई कार इकाई 4 टायरों की सरणी से जुड़ी है ... यदि एक टायर या अधिक शून्य है ... अपवाद को "NotEnoughTiresException" निकाल दिया जाना चाहिए, cuz इसे सिस्टम के विभिन्न स्तर पर पकड़ा जा सकता है और एक महत्वपूर्ण है लॉगिंग के माध्यम से मतलब है। इसके अलावा अगर हम सिर्फ नल को नियंत्रित करने की कोशिश करते हैं और कार की अस्थिरता को रोकते हैं। we might never never find the source of the problem , cuz the tire isn't supposed to be null in the first place .


मैं कहूंगा कि आम तौर पर हर कट्टरतावाद नरक की ओर जाता है।

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

जो मैं आम तौर पर पसंद करता हूं वह दो बुनियादी प्रकार के अपवादों को बनाना है जो पूरे सिस्टम में उपयोग किए जाते हैं: LogicalException और TechnicalException । यदि आवश्यक हो तो इन्हें उपप्रकारों द्वारा आगे बढ़ाया जा सकता है, लेकिन आमतौर पर यह आवश्यक नहीं है।

तकनीकी अपवाद वास्तव में अप्रत्याशित अपवाद को इंगित करता है जैसे डेटाबेस सर्वर डाउन हो रहा है, वेब सेवा के कनेक्शन ने IOException को फेंक दिया और इसी तरह।

दूसरी तरफ तार्किक अपवादों का उपयोग ऊपरी परतों (आमतौर पर कुछ सत्यापन परिणाम) में कम गंभीर ग़लत स्थिति को प्रसारित करने के लिए किया जाता है।

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

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

हमारा सामान्य उपयोग वेब सेवा कॉल के दौरान LogicalException को फेंकना है जब उपयोगकर्ता का इनपुट अमान्य था। अपवाद को SOAPFault विवरण में घुसपैठ कर दिया जाता है और फिर क्लाइंट पर अपवाद के लिए अनमोल हो जाता है जिसके परिणामस्वरूप एक निश्चित वेब पेज इनपुट फ़ील्ड पर सत्यापन त्रुटि दिखाई दे रही है क्योंकि अपवाद के उस क्षेत्र में उचित मैपिंग है।

यह निश्चित रूप से एकमात्र स्थिति नहीं है: अपवाद को फेंकने के लिए आपको वेब सेवा को हिट करने की आवश्यकता नहीं है। आप किसी भी असाधारण स्थिति में ऐसा करने के लिए स्वतंत्र हैं (जैसे कि आपको असफल होने की आवश्यकता है) - यह सब आपके विवेकाधिकार पर है।


मैं वहां जॅपॉकॉक तरीके से सहमत हूं - एक ऑपरेशन के नतीजे के बारे में अनिश्चित होने पर एक धारणा फेंक दें। एपीआई को कॉल करता है, फाइल सिस्टम, डेटाबेस कॉल इत्यादि एक्सेस करता है। कभी भी आप अपनी प्रोग्रामिंग भाषाओं की "सीमाओं" से आगे बढ़ रहे हैं।

मैं जोड़ना चाहता हूं, एक मानक अपवाद फेंकने के लिए स्वतंत्र महसूस करें। जब तक आप कुछ "अलग" करने के लिए नहीं जा रहे हैं (अनदेखा करें, ईमेल करें, लॉग करें, ट्विटर व्हेल चित्र चीज़ आदि दिखाएं), तो कस्टम अपवादों से परेशान न हों।


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

तो, संक्षिप्त जवाब यह है कि यदि यह एक महत्वपूर्ण प्रदर्शन जुर्माना नहीं देता है (जो तब तक नहीं होना चाहिए जब तक कि आप बहुत सारे अपवाद नहीं फेंक रहे हों), फिर आगे बढ़ें।


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

चूंकि यह जानना संभव नहीं है कि आपके उपयोगकर्ताओं के लिए क्या उपयोगी हो सकता है, इसलिए विशिष्ट अपवादों का बेहतर दृष्टिकोण है, लेकिन यह सुनिश्चित करें कि वे एक सामान्य वर्ग (जैसे, std :: अपवाद या सी ++ में इसके डेरिवेटिव) से प्राप्त होते हैं। इससे आपके ग्राहक को विशिष्ट अपवादों को पकड़ने की अनुमति मिलती है, यदि वे चुनते हैं, या यदि वे परवाह नहीं करते हैं तो अधिक सामान्य अपवाद।


सुरक्षा आपके उदाहरण के साथ उलझी हुई है: आपको किसी हमलावर को यह नहीं कहना चाहिए कि उपयोगकर्ता नाम मौजूद है, लेकिन पासवर्ड गलत है। यह अतिरिक्त जानकारी है जिसे आपको साझा करने की आवश्यकता नहीं है। बस कहें "उपयोगकर्ता नाम या पासवर्ड गलत है।"


"PasswordNotCorrectException" isn't a good example for using exceptions. Users getting their passwords wrong is to be expected, so it's hardly an exception IMHO. You probably even recover from it, showing a nice error message, so it's just a validity check.

Unhandled exceptions will stop the execution eventually - which is good. If you're returning false, null or error codes, you will have to deal with the program's state all by yourself. If you forget to check conditions somewhere, your program may keep running with wrong data, and you may have a hard time figuring out what happened and where .

बेशक, आप खाली पकड़ वक्तव्य के साथ एक ही समस्या पैदा कर सकते हैं, लेकिन कम से कम उनको ढूंढना आसान है और आपको तर्क को समझने की आवश्यकता नहीं है।

तो अंगूठे का नियम के रूप में:

जहां भी आप नहीं चाहते हैं उनका उपयोग करें या बस एक त्रुटि से ठीक नहीं हो सकता है।


There are two main classes of exception:

1) System exception (eg Database connection lost) or 2) User exception. (eg User input validation, 'password is incorrect')

I found it helpful to create my own User Exception Class and when I want to throw a user error I want to be handled differently (ie resourced error displayed to the user) then all I need do in my main error handler is check the object type:

            If TypeName(ex) = "UserException" Then
               Display(ex.message)
            Else
               DisplayError("An unexpected error has occured, contact your help  desk")                   
               LogError(ex)
            End If

Ultimately the decision comes down to whether it is more helpful to deal with application-level errors like this using exception handling, or via your own home-rolled mechanism like returning status codes. I don't think there's a hard-and-fast rule about which is better, but I would consider:

  • Who's calling your code? Is this a public API of some sort or an internal library?
  • What language are you using? If it's Java, for example, then throwing a (checked) exception puts an explicit burden on your caller to handle this error condition in some way, as opposed to a return status which could be ignored. That could be good or bad.
  • How are other error conditions in the same application handled? Callers won't want to deal with a module that handles errors in an idiosyncratic way unlike anything else in the system.
  • How many things can go wrong with the routine in question, and how would they be handled differently? Consider the difference between a series of catch blocks that handle different errors and a switch on an error code.
  • Do you have structured information about the error you need to return? Throwing an exception gives you a better place to put this information than just returning a status.




language-agnostic