वेक्सिंग अपवादों को फेंकने से कैसे बचें?


21

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

विशेष रूप से:

  • मान लीजिए कि आपके पास एक बचत विधि है जो विफल हो सकती है क्योंकि a) किसी और ने आपके सामने रिकॉर्ड को संशोधित किया है , या b) वह मान जिसे आप पहले से मौजूद बनाने का प्रयास कर रहे हैं । इन स्थितियों की उम्मीद की जानी चाहिए और असाधारण नहीं है, इसलिए एक अपवाद को फेंकने के बजाय, आप अपनी पद्धति का एक कोशिश संस्करण बनाने का निर्णय लेते हैं, ट्राइसेव, जो एक बूलियन को संकेत देता है कि क्या बचत सफल हुई। लेकिन अगर यह विफल हो जाता है, तो उपभोक्ता कैसे जानेंगे कि समस्या क्या थी? या परिणाम का संकेत करने वाले एक एनुम को वापस करना सबसे अच्छा होगा, ओके / रिकॉर्डअलरेडीमोडिफाइड / वैल्यूएलाइजिस्ट्स की तरह? Integer.TryParse के साथ यह समस्या मौजूद नहीं है, क्योंकि केवल एक ही कारण विधि विफल हो सकती है।
  • क्या पिछला उदाहरण वास्तव में एक विकट स्थिति है? या इस मामले में एक अपवाद को फेंकना पसंदीदा तरीका होगा? मुझे पता है कि एंटिटी ढांचे सहित अधिकांश पुस्तकालयों और रूपरेखाओं में यह कैसे किया जाता है।
  • आप यह कैसे तय करते हैं कि अपनी विधि का एक आज़माया हुआ संस्करण कैसे बनाया जाए? मैं वर्तमान में इन दिशानिर्देशों का पालन कर रहा हूं:
    • यदि दौड़ की स्थिति का मौका है, तो एक कोशिश संस्करण बनाएं। यह उपभोक्ता के लिए एक बाहरी अपवाद को पकड़ने की आवश्यकता को रोकता है। उदाहरण के लिए, पहले बताई गई सेव विधि में।
    • यदि विधि को बहुत अधिक परीक्षण करने की विधि मूल विधि से सभी करती है, तो एक कोशिश संस्करण बनाएं। उदाहरण के लिए, integer.TryParse ()।
    • किसी अन्य मामले में, स्थिति का परीक्षण करने के लिए एक विधि बनाएं।

1
आपके द्वारा सहेजे जाने का एक उदाहरण जो विफल हो सकता है वह वास्तव में बहुत घबराहट अपवाद नहीं है। यह काफी सामान्य है और शायद बस एक अपवाद होना चाहिए
S.Lott

@ एस.लॉट: आप के साथ क्या मतलब है यह काफी सामान्य है? इस स्थिति में ही स्थिति, या अपवाद को फेंकना? वैसे भी, मैं आपसे सहमत हूं कि यह स्पष्ट नहीं है कि क्या यह वास्तव में एक भयावह स्थिति है। मैं सवाल को अपडेट करूंगा।
माइक

"स्थिति खुद, या इस स्थिति में एक अपवाद फेंक" दोनों।
S.Lott

जवाबों:


24

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

अच्छा प्रश्न।

पहला सवाल जो मेरे दिमाग में आता है वह है: यदि डेटा पहले से है तो किस मायने में सेव फेल हुआ ? मुझे यकीन है कि यह मेरे लिए सफल रहा। लेकिन चलो तर्क के लिए मान लें कि आपके पास वास्तव में कई अलग-अलग कारण हैं कि एक ऑपरेशन विफल क्यों हो सकता है।

दूसरा सवाल यह है कि मेरे दिमाग में आता है: जानकारी आप उपयोगकर्ता पर वापस लौटना चाहते है कार्रवाई योग्य ? यही है, क्या वे उस जानकारी के आधार पर कुछ निर्णय लेने जा रहे हैं?

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

क्या कॉलर परवाह करता है कि बचत क्यों विफल रही? क्या वे इसके बारे में कुछ भी करने जा रहे हैं, या तो छोड़ दें या फिर कोशिश करें?

आइए इस तर्क के लिए मान लें कि कॉल करने वाला वास्तव में ऑपरेशन के विफल होने के कारण के आधार पर अलग-अलग कार्रवाई करने जा रहा है।

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

आइए तर्क के लिए मान लें कि यह अनैच्छिक है।

चौथा सवाल जो दिमाग में आता है वह है: क्या समय से पहले खराब स्थिति का मज़बूती से पता लगाने का एक तरीका है?

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

पांचवा प्रश्न जो मन में आता है वह है: क्या एपीआई को डिजाइन करने का एक तरीका है ताकि खराब स्थिति को रोका जा सके?

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


सभी बहुत अच्छे अंक, धन्यवाद। अब यहाँ एक आलंकारिक प्रश्न है जो शायद मेरी पोस्ट को सारांशित करता है: यदि आप File.Open को फिर से डिज़ाइन करना चाहते थे, तो क्या आप इसके बजाय एक File.TryOpen () बनाएँगे? आप उपभोक्ता को विफल होने का कारण कैसे बताएंगे? या वास्तव में सबसे अच्छा समझौता यहाँ एक बहिर्जात अपवाद फेंक रहा है?
माइक

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

मैं इस प्रश्न का उत्तर देने के लिए विचार करता हूं, लेकिन मैं अभी उत्सुक हूं;) यदि विधि 2 या अधिक कारणों से विफल हो सकती है, तो विफलताएं कार्रवाई योग्य हैं, असफलताएं अनपेक्षित हैं और विफलताओं का समय से पहले पता नहीं लगाया जा सकता है और न ही रोका जा सकता है। तुम क्या करोगे?
माइक

@ माइक मैं एरिक के लिए नहीं बोल सकता, लेकिन यह त्रुटि कोड के लिए एक अच्छी जगह की तरह लगता है। एक एनुम का सदस्य लौटना, शायद।
मैथ्यू पढ़ें

1

आपके उदाहरण में, यदि ValueAlreadyExists स्थिति को आसानी से जांचा जा सकता है, तो इसे जाँचना चाहिए और सहेजें को आज़माने से पहले एक अपवाद उठाया जा सकता है, मुझे नहीं लगता कि इस स्थिति में एक प्रयास आवश्यक होना चाहिए। दौड़ की स्थिति समय से पहले जांचना कठिन है, इसलिए इस मामले में एक कोशिश में सहेजें लपेटना शायद एक बहुत अच्छा विचार है।

सामान्य तौर पर, अगर ऐसी स्थिति है जो मुझे लगता है कि बहुत अधिक संभावना है (जैसे कि NoDataReturned, DivideByZero, आदि ...) या (जैसे खाली संग्रह या NULL-value) की जांच करना बहुत आसान है, तो मैं जांचने की कोशिश नहीं करता। समय से पहले और इससे पहले कि मैं उस बिंदु पर पहुंच जाऊं, जहां मुझे एक अपवाद को पकड़ना है। मैं मानता हूं कि समय से पहले इन स्थितियों को जानना हमेशा आसान नहीं होता है, कभी-कभी वे केवल तब दिखाई देते हैं जब कोड कठोर परीक्षण के तहत होता है।


0

save()विधि एक अपवाद फेंक चाहिए।

शीर्ष-सबसे परत को प्रोग्राम को समाप्त किए बिना, उपयोगकर्ता को पकड़ना और सूचित करना चाहिए , जब तक कि यह कमांड लाइन कार्यक्रमों की तरह यूनिक्स नहीं है, जिस स्थिति में इसे समाप्त करना ठीक है।

अपवादों को प्रबंधित करने के लिए रिटर्न मान एक अच्छा तरीका नहीं है।

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