2008-10-13 8 views
6

शीर्षक वास्तव में यह नहीं समझा सकता कि मैं वास्तव में क्या करने की कोशिश कर रहा हूं, वास्तव में मेरे मतलब का वर्णन करने के तरीके के बारे में सोच नहीं सकता।क्या मुझे यह सुनिश्चित करना चाहिए कि फ़ंक्शन में उनका उपयोग करने से पहले तर्क शून्य नहीं हैं?

मैं सोच रहा था कि क्या यह कार्य उन तर्कों की जांच करने के लिए अच्छा अभ्यास है जो किसी फ़ंक्शन को नल के लिए स्वीकार करते हैं या उन्हें उपयोग करने से पहले खाली करते हैं। मेरे पास यह फ़ंक्शन है जो कुछ हैश सृजन को इस तरह लपेटता है।

Public Shared Function GenerateHash(ByVal FilePath As IO.FileInfo) As String 
     If (FilePath Is Nothing) Then 
      Throw New ArgumentNullException("FilePath") 
     End If 

     Dim _sha As New Security.Cryptography.MD5CryptoServiceProvider 
     Dim _Hash = Convert.ToBase64String(_sha.ComputeHash(New IO.FileStream(FilePath.FullName, IO.FileMode.Open, IO.FileAccess.Read))) 
     Return _Hash 
    End Function 

आप देख सकते हैं मैं सिर्फ समारोह मुझे यकीन है कि यह कुछ भी नहीं नहीं है बनाने के लिए जाँच कर रहा हूँ के शुरू में, एक तर्क के रूप में एक IO.Fileinfo लेता है।

मुझे आश्चर्य है कि यह अच्छा अभ्यास है या क्या मुझे इसे वास्तविक हैशर तक पहुंचने देना चाहिए और फिर अपवाद फेंकना क्योंकि यह शून्य है।

धन्यवाद।

उत्तर

20

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

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

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

1

यदि न्यूल एक अस्वीकार्य इनपुट है, तो अपवाद फेंक दें। अपने आप से, जैसे आपने अपने नमूने में किया था, ताकि संदेश सहायक हो।

नल इनपुट को संभालने का एक और तरीका बदले में एक नल के साथ राहत देना है। फ़ंक्शन के प्रकार पर निर्भर करता है - ऊपर दिए गए उदाहरण में मैं अपवाद रखूंगा।

1

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

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

0

अधिकांश समय, इसे अपवाद फेंकने देना बहुत उचित है जब तक कि आप सुनिश्चित हैं कि अपवाद को अनदेखा नहीं किया जाएगा।

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

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

मुझे चर और तर्कों पर "शून्य" या "नल" संशोधक देखना अच्छा लगेगा ताकि संकलक आपके लिए जांच सके।

2

हां, किसी विधि की शुरुआत में सभी तर्कों को मान्य करने और ArgumentException, ArgumentNullException, या ArgumentOutOfRangeException जैसे उपयुक्त अपवादों को फेंकना अच्छा अभ्यास है।

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

3

सी ++ में मेरी पसंदीदा तकनीकों में से एक NULL पॉइंटर्स पर DEBUG_ASSERT था। यह मुझे वरिष्ठ प्रोग्रामर (कॉन्स शुद्धता के साथ) द्वारा ड्रिल किया गया था और कोड समीक्षाओं के दौरान मैं सबसे सख्त चीजों में से एक था। हम कभी पहले बिना किसी संकेत के एक संकेतक को अस्वीकार कर दिया गया था, यह शून्य नहीं था।

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

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

0

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

यदि आप एक एपीआई लिख रहे हैं जहां कॉलर अविश्वसनीय (या कॉलर का कॉलर) हो सकता है, तो वैध इनपुट के लिए चेक किया गया है, क्योंकि यह अच्छी सुरक्षा है।

यदि आपके एपीआई विश्वसनीय कॉलर्स द्वारा केवल पहुंच योग्य हैं, जैसे सी # में "आंतरिक", तो ऐसा नहीं लगता कि आपको वह अतिरिक्त कोड लिखना है। यह किसी के लिए उपयोगी नहीं होगा।

1

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

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

वही बात किसी भी अन्य धारणा पर लागू होती है।

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

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

1

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

अनुबंध द्वारा क्लासिक डिजाइन: यदि इनपुट सही है, तो उत्पादन सही होगा। अगर इनपुट गलत है, तो एक बग है।

+0

और यदि इनपुट गलत है और आउटपुट सही है ... एचआरएम .. यह इतना अच्छा नहीं है। – stephenbayer

1

मैं अनुबंध सलाह पहले ब्रायन द्वारा offerred द्वारा उत्कृष्ट डिजाइन के विस्तारण के एक जोड़े (बोल्ड में ) जोड़ देंगे (यदि इनपुट सही है, लेकिन उत्पादन गलत है, एक बग है। यही कारण है कि एक गिम्मी है।)। ..

"अनुबंध द्वारा डिजाइन" के प्रधानाचार्यों की आवश्यकता है कि आप कॉलर के लिए (इनपुट मानों का वैध डोमेन) में प्रवेश करने के लिए स्वीकार्य है और फिर, किसी वैध इनपुट के लिए, विधि/प्रदाता क्या करेगा ।

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

अब, बहुत अच्छी तरह से परिभाषित और पार्सिमोनियस के दौरान, यदि आप बाहरी/सार्वजनिक कॉलर्स के लिए विधि का खुलासा कर रहे हैं, तो आपको खुद से पूछना चाहिए, क्या मैं वास्तव में अनुबंध चाहता हूं? शायद नहीं। एक सार्वजनिक इंटरफ़ेस में, आप शायद NULL (तकनीकी रूप से इनपुट के डोमेन में जो विधि स्वीकार करते हैं) स्वीकार करते हैं, लेकिन फिर शानदार रूप से w/एक रिटर्न संदेश संसाधित करने में अस्वीकार करते हैं। (स्वाभाविक रूप से अधिक जटिल ग्राहक-सामना करने की आवश्यकता को पूरा करने के लिए अधिक काम।)

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

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

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