2009-03-09 11 views
7

मैं MSDN में चारों ओर खुदाई और this article जो सलाह के एक दिलचस्प सा था पाया गया था: सार्वजनिक सदस्यों है कि या तो फेंक कर सकते हैं या कुछ विकल्प के आधार पर अपवाद फेंक नहीं नहीं है।एक पैरामीटर के आधार पर एक अपवाद फेंक दो/नहीं-फेंकना - यह एक अच्छा विचार क्यों नहीं है?

उदाहरण के लिए:

Uri ParseUri(string uriValue, bool throwOnError) 

अब निश्चित रूप से मुझे लगता है कि मामलों इस भयानक होगा के 99% में देख सकते हैं, लेकिन इसके लिए प्रासंगिक उपयोग उचित है? जब डेटाबेस या एक विन्यास फाइल में डेटा तक पहुँचने

ही एक मामला मैंने देखा है यह प्रयोग किया जाता एक "AllowEmpty" पैरामीटर के साथ है। उदाहरण के लिए:

object LoadConfigSetting(string key, bool allowEmpty); 

इस मामले में, विकल्प शून्य वापस लौटना होगा। लेकिन फिर कॉलिंग कोड शून्य संदर्भों के साथ भरेगा। (और यदि आप इतने इच्छुक थे तो विधि वास्तव में विशेष रूप से कॉन्फ़िगर करने योग्य मान के रूप में शून्य को अनुमति देने की क्षमता को रोक देगा)।

आपके क्या विचार हैं? यह एक बड़ी समस्या क्यों होगी?

उत्तर

9

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

यह इस मामले में 2 एपीआई रखने के लिए बहुत बेहतर और अधिक पठनीय होगा।

Uri ParseUriOrThrow(string value); 

bool TryParseUri(string value, out Uri uri); 

इस मामले में यह 100% स्पष्ट है कि ये API क्या करते हैं। क्यों बूलियन्स पैरामीटर के रूप में बुरा कर रहे हैं पर

अनुच्छेद: http://blogs.msdn.com/jaredpar/archive/2007/01/23/boolean-parameters.aspx

3

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

उपरोक्त उदाहरण में, यदि पार्स विफल रहता है और throwOnError गलत है क्या होता है? अब उपयोगकर्ता को अनुमान लगाना है कि अगर वापस लौटाया जा रहा है, या भगवान जानता है ...

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

1

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

हालांकि, मुझे लगता है कि MSDN लेख को कड़ाई से 'throwOnError' झंडे की चर्चा करते हुए किया गया है। इन मामलों में या तो त्रुटि को विधि के अंदर अनदेखा किया जाता है (खराब, जैसा कि यह छिपा हुआ है) या किसी प्रकार की शून्य/त्रुटि वस्तु वापस आती है (खराब, क्योंकि आप त्रुटि को संभालने के लिए अपवादों का उपयोग नहीं कर रहे हैं, जो असंगत है और स्वयं त्रुटि है -prone)।

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

0

इस के साथ लाइन में एक और उदाहरण मूल्य प्रकार के कुछ

bool DateTime.TryParse(string text, out DateTime)

1

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

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

0

donTThrowException पैरामीटर होने के बाद अपवादों (किसी भी भाषा में) के पूरे बिंदु को हराया जाता है।

public static void Main() 
{ 
     FileStream myFile = File.Open("NonExistent.txt", FileMode.Open, FileAccess.Read); 
} 

वे (सी # भी जाँच की है नहीं करता है अपवाद) के लिए स्वागत कर रहे हैं: बुला कोड है चाहता है।

public static void main(String[] args) throws FileNotFoundException 
{ 
     FileInputStream fs = new FileInputStream("NonExistent.txt"); 
} 

किसी भी तरह से, यह फोन करने वाले का काम है कैसे संभाल करने के लिए (या नहीं) तय करने के लिए अपवाद, नहीं कॉल प्राप्त करने वाला का: जावा में एक ही बात के साथ पूरा किया जाएगा।

0

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

जेफरी रिचर्स सी # अंक के माध्यम से सीएलआर बुक करें - "जब आप विधि अपने नाम से संकेत के अनुसार अपना कार्य पूरा नहीं कर सकते हैं तो आपको अपवाद फेंकना चाहिए"।

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

मुझे अपवाद है कि मैं उम्मीद कर सकते हैं के लिए कोड की कोशिश करते हैं और मेरे तर्क में संभाल कर सकते हैं अन्यथा यह होना चाहिए बना दिया है कि एक त्रुटि।

अपने तर्कों को मान्य करें और अपवादों को रोकें, और केवल आप जो संभाल सकते हैं उसे पकड़ लें।

+0

मुझे लगता है कि आप scen गलत समझा है ario। हमारे पास एक अपवाद फेंकने का विकल्प है (जो प्रोग्राम या जो कुछ भी रोक देगा), या अपवाद फेंक नहीं सकता है (यानी शून्य वापस करें या कुछ भी नहीं करें)। किसी भी मामले में अपवाद फेंक दिए जाते हैं और फिर पकड़े जाते हैं। – cbp

0

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

बाइट [] ReadPacket (bool DontThrowIfNone) // अशक्त अगर कोई { पूर्णांक लेन = ReadByte (DontThrowIfNone) लौटने के रूप में प्रलेखित; // लौटने के रूप में प्रलेखित -1 यदि कुछ भी यदि (लेन

यदि डेटा पढ़ने के दौरान टाइमआउट अपवाद की तरह कुछ अपवाद का कारण बनना चाहिए, तो ऐसे अपवाद को रीडबेट() या ReadMultiBytesbytes() के भीतर फेंक दिया जाना चाहिए। यदि, हालांकि, डेटा की कमी को सामान्य माना जाना चाहिए, फिर ReadByte() या ReadMultiBytesbytes() दिनचर्या को अपवाद नहीं फेंकना चाहिए। अगर किसी ने बस/प्रयास पैटर्न का उपयोग किया है, तो रीडपैकेट और TryReadPacket रूटीन में लगभग समान कोड होना आवश्यक है, लेकिन एक का उपयोग कर पढ़ें * तरीके और अन्य का उपयोग कर TryRead * तरीकों के साथ। को भावुक।

यह एक बूलियन बजाय एक गणन उपयोग करने के लिए बेहतर हो सकता है।

संबंधित मुद्दे