2008-09-14 13 views
33

मैंने जॉन रॉबिन्स द्वारा 'डीबगिंग एमएस नेट 2.0 एप्लीकेशन' को स्किमिंग करना शुरू कर दिया है, और डीबग.एस्र्ट (...) के लिए अपने सुसमाचार प्रचार से भ्रमित हो गए हैं।डीबग.एस्र्ट बनाम विशिष्ट थ्रोउन अपवाद

वे बताते हैं कि अच्छी तरह से लागू किया राज्य की दुकान दावा कुछ हद तक, एक त्रुटि हालत का, जैसे:

Debug.Assert(i > 3, "i > 3", "This means I got a bad parameter"); 

अब, व्यक्तिगत रूप से, यह मेरे लिए पागल है कि वह तो अपने परीक्षण restating प्यार करता है एक के बिना लगता है वास्तविक समझदार 'व्यापार तर्क' टिप्पणी, शायद "i < = 3 flobittyjam widgitification प्रक्रिया के कारण कभी नहीं होना चाहिए"।

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

लेकिन मुझे जो नहीं मिलता है, वह तब कहता है कि आपको सामान्य त्रुटि प्रबंधन के अलावा दावे का उपयोग करना चाहिए; अब मैं इस पर कुछ विचार कर रहा हूं:

Debug.Assert(i > 3, "i must be greater than 3 because of the flibbity widgit status"); 
if (i <= 3) 
{ 
    throw new ArgumentOutOfRangeException("i", "i must be > 3 because... i=" + i.ToString()); 
} 

मुझे डीबग द्वारा प्राप्त किया गया है। त्रुटि स्थिति परीक्षण की पुन: पुनरावृत्ति? मुझे लगता है कि मैं अगर हम डिबग-केवल एक बहुत ही महत्वपूर्ण गणना की दो बार जांच के बारे में बात कर रहे थे इसे पाने होगी ...

double interestAmount = loan.GetInterest(); 
Debug.Assert(debugInterestDoubleCheck(loan) == interestAmount, "Mismatch on interest calc"); 

... लेकिन मैं पैरामीटर परीक्षण जो निश्चित रूप से लायक हैं के लिए यह नहीं मिलता है जांच (दोनों DEBUG और रिलीज बिल्ड में) ... या नहीं। मैं क्या खो रहा हूँ?

उत्तर

48

दावा पैरामीटर जांच के लिए नहीं हैं। पैरामीटर जांच हमेशा की जानी चाहिए (और सटीक रूप से आपके दस्तावेज़ और/या विनिर्देश में पूर्व-शर्तों को निर्दिष्ट किया गया है), और ArgumentOutOfRangeException आवश्यकतानुसार फेंक दिया गया है।

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

आशा है कि इससे मदद मिलती है!

+10

दावे * आंतरिक * विधि कॉल के पैरामीटर की जाँच के तरीकों (एक ही घटक से संबंधित कोड द्वारा कहा जाता है) के लिए इस्तेमाल किया जा सकता है, के रूप में बाहरी विधि कॉल (एक और घटक द्वारा कहा जाता है) करने का विरोध किया । उदाहरण के लिए, मैं जोर दे सकता हूं कि टाइप डबल का एक निजी विधि पैरामीटर NaN नहीं है। – RoadWarrior

+0

@ क्रिस: आप बताते हैं कि मानदंड पैरामीटर जांच के लिए उपयोग नहीं किया जाना चाहिए। क्या इसका कोई कारण है? जब मैं निर्भर वस्तुओं को इंजेक्ट करता हूं तो मैं विशेष रूप से रचनाकारों में पैरामीटर चेक के लिए अपवाद फेंक देता हूं। हालांकि मुझे Assertions का उपयोग करने के लिए कहा जा रहा है। मेरे पास दावे के बजाय अपवादों का उपयोग करने के लिए तार्किक स्पष्टीकरण नहीं है। क्या आप स्पष्टीकरण में सक्षम हैं? चीयर्स –

+7

चिंता मत करो मुझे पता चला क्यों। जॉन स्कीट के मुताबिक, http://stackoverflow.com/questions/1276308/exception-vs-assertion: "अपने कोड के भीतर आंतरिक तर्क जांच के लिए दावे का उपयोग करें, और अपने तत्काल कोड के नियंत्रण के बाहर त्रुटि स्थितियों के लिए सामान्य अपवाद।" –

2

आईएमओ यह केवल विकास के समय का नुकसान है। उचित रूप से कार्यान्वित अपवाद आपको जो हुआ उससे स्पष्ट तस्वीर देता है। मैंने देखा बहुत अधिक अस्पष्ट दिखने वाले अनुप्रयोग "Assertion विफल: i < 10" त्रुटियां। मैं एक अस्थायी समाधान के रूप में दावा देखते हैं। मेरी राय में किसी कार्यक्रम के अंतिम संस्करण में कोई दावा नहीं होना चाहिए। मेरे अभ्यास में मैंने त्वरित और गंदे चेक के लिए दावे का इस्तेमाल किया। कोड के अंतिम संस्करण को गलत स्थिति को ध्यान में रखना चाहिए और तदनुसार व्यवहार करना चाहिए। यदि कुछ बुरा होता है तो आपके पास 2 विकल्प होते हैं: इसे संभालें या छोड़ दें। गलत पैरामीटर पारित होने पर फ़ंक्शन को अर्थपूर्ण विवरण के साथ अपवाद फेंकना चाहिए। मुझे सत्यापन तर्क के दोहराव में कोई अंक नहीं दिखता है।

4

मैं स्पष्ट जांच करता है कि सार्वजनिक और संरक्षित तरीकों और निजी तरीकों पर दावे पर अपवाद फेंक का उपयोग करें।

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

17

हमरेट फेंकने के लिए जोर देने के लिए एक संचार पहलू है।

मान लें कि हमारे पास नाम संपत्ति और एक ToString विधि वाला उपयोगकर्ता वर्ग है।

ToString इस तरह कार्यान्वित किया जाता है, तो:

public string ToString() 
{ 
    Debug.Assert(Name != null); 
    return Name; 
} 

ऐसा नहीं है कि नाम कभी नहीं अशक्त चाहिए कहते हैं और वहाँ उपयोगकर्ता वर्ग में एक बग अगर यह होता है है।

तो ToString इस तरह लागू है:

public string ToString() 
{ 
    if (Name == null) 
    { 
      throw new InvalidOperationException("Name is null"); 
    } 

    return Name; 
} 

इसमें कहा गया है कि फोन करने वाले ToString उपयोग कर रहा है गलत तरीके से करता है, तो नाम रिक्त है और जांच करनी चाहिए कि कॉल करने से पहले।

कार्यान्वयन दोनों

public string ToString() 
{ 
    Debug.Assert(Name != null); 
    if (Name == null) 
    { 
      throw new InvalidOperationException("Name is null"); 
    } 

    return Name; 
} 

साथ कहते हैं कि यदि नाम उपयोगकर्ता कक्षा में वहाँ बग रिक्त है, लेकिन हम किसी तरह इसे संभाल करने के लिए चाहते हैं। (उपयोगकर्ता को कॉल करने से पहले नाम की जांच करने की आवश्यकता नहीं है।) मुझे लगता है कि यह रॉबिन की सुरक्षा की तरह है।

3

एक अपवाद पकड़ा जा सकता है और त्रुटि को जांचने के लिए अदृश्य बना दिया जा सकता है। यह Debug.Assert के साथ नहीं हो सकता है।

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

जब अपवाद को अनचाहे किया जाएगा, तब भी एक बेहतर अभ्यास मिनी-डंप लेना है। एक क्षेत्र जहां वीबी सी # से अधिक शक्तिशाली है, यह है कि जब आप अपवाद में होते हैं तो मिनी-डंप को स्नैप करने के लिए अपवाद फ़िल्टर का उपयोग कर सकते हैं, और शेष अपवाद हैंडलिंग अपरिवर्तित छोड़ दें। Gregg Miskelly's blog post on exception filter inject सी # से ऐसा करने का एक उपयोगी तरीका प्रदान करता है।

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

0

यहां 2 सेंट है।

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

प्रत्येक एप्लिकेशन अपवाद सही ढंग से संभाला जाएगा, जबकि दावा केवल एल्गोरिदम विकास और परीक्षण के दौरान संतुष्ट होंगे।

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

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

4

मैंने परीक्षण चिंताओं के संबंध में डीबग बनाम जोर देने पर मार्गदर्शन प्रदान करने के बारे में सोचा है।

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

अंगूठे का अच्छा नियम मैं पर पहुंच गए:

  1. का दावा मजबूत कोड है कि कार्यों विन्यास का सही ढंग से स्वतंत्र के लिए एक स्थानापन्न नहीं हैं। वे पूरक हैं।

  2. अमान्य मानों या परीक्षण त्रुटि स्थितियों में भोजन करते समय भी यूनिट परीक्षण चलाने के दौरान आवेषणों को कभी नहीं छोड़ा जाना चाहिए। कोड को बिना किसी जोर के इन शर्तों को संभालना चाहिए।

  3. यदि कोई जोरदार यात्रा (या तो इकाई परीक्षण में या परीक्षण के दौरान), कक्षा को खराब किया जाता है।

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

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

1

उदाहरण:

Debug.Assert(flibbles.count() < 1000000, "too many flibbles"); // indicate something is awry 
log.warning("flibble count reached " + flibbles.count()); // log in production as early warning 

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

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

सीएफ।http://c2.com/cgi/wiki?FailFast की नकल की और जावा सवाल से संशोधित: Exception Vs Assertion

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