2010-10-29 18 views
7

यह जांचने के लिए दावा किया जाता है कि कोई शर्त पूरी हो गई है (पूर्व शर्त, पोस्टकंडिशन, इनवेरिएंट) और प्रोग्रामर को डिबगिंग चरण के दौरान छेद खोजने में सहायता करें।यदि दावा विफल रहता है तो रणनीति क्या है

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

void f(int *p) 
{ 
    assert(p); 
    p->do(); 
} 

मेरा प्रश्न है हम यह मान हालत रिलीज़ मोड में पूरा नहीं किया जा सकता है और उसके अनुसार मामले को संभालने की जरूरत है?

void f(int *p) 
{ 
    assert(p); 

    if (p) 
    { 
    p->do(); 
    } 
} 

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

+2

[डुप्लिकेट [अनुबंध द्वारा परीक्षण द्वारा अपवाद या अपवाद द्वारा डिजाइन?] (Http://stackoverflow.com/questions/117171/design-by-contract-tests-by-assert-or-by-exception) (वहां है विभिन्न दृष्टिकोणों के पेशेवरों और विपक्ष के बारे में बहुत अच्छी चर्चा; इस विषय पर वास्तव में सर्वसम्मति नहीं है) यह भी देखें [कब उत्पादन कोड में दावा कब रहना चाहिए?] (http: // stackoverflow।कॉम/प्रश्न/17732/कब-कथन-रह-इन-प्रोडक्शन-कोड) –

+0

मुझे नहीं लगता कि मैंने कभी एक प्रश्न देखा है जो इतने कम समय में इतने सारे प्रतिक्रिया प्राप्त करता है। –

+0

हाँ, और प्रत्येक एक दूसरे के विरोधाभास :) – EboMike

उत्तर

20

यदि दावा विफल रहता है, प्रोग्राम को क्रैश करना चाहिए।

एक दावा विफल करने का मतलब है कि प्रोग्रामर ने अपनी समझ में एक मौलिक गलती की है कि कार्यक्रम प्रवाह के लिए यह कैसे संभव है। यह एक विकास सहायता है, न कि उत्पादन सहायता। उत्पादन में, अपवाद को संभाल सकता है, क्योंकि वे "हो सकता है", जबकि दावे को "कभी नहीं" विफल होना चाहिए।

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

सामान्य शब्दों में, जोरनहीं है बस के लिए एक आशुलिपि "अगर हालत नहीं मिले थे, फेंक अपवाद" (अच्छी तरह से, कभी कभी कि परिचालन अर्थ विज्ञान है, लेकिन यह denotational अर्थ विज्ञान नहीं है)। इसके बजाय, एक दावा विफल करने का मतलब है कि आवेदन में एक राज्य है जिसे डेवलपर विश्वास नहीं करता है संभव। क्या आप वाकई कोड को ऐसे मामले में निष्पादित करना जारी रखना चाहते हैं? स्पष्ट रूप से (मैं कहूंगा), नहीं

+0

+1 आप सही हैं सर। – frast

+0

ध्यान दें कि मेरा उत्तर * स्पष्ट रूप से * उत्पादन रिलीज में दावाों को शामिल नहीं किया जाना चाहिए या नहीं, इस धारणा को स्पष्ट रूप से संबोधित नहीं किया गया है, क्योंकि यह प्रश्न के दायरे से बाहर है। – user359996

0

दावा डीबगिंग कोड हैं, ऑपरेटिंग कोड नहीं। इनपुट त्रुटियों को पकड़ने के लिए उनका उपयोग न करें।

0

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

यदि वास्तविक जीवन परिचालन में स्थिति उत्पन्न हो सकती है तो कोई संभावना है, तो दावे पर भरोसा न करें - अपवाद या कुछ अन्य त्रुटि तंत्र का उपयोग करें।

+0

तो क्या मुझे पूरी तरह से परीक्षण किए जाने पर रिलीज़ मोड में दावों को हटाने की आवश्यकता है? या कोड को बनाए रखने वाले किसी अन्य डेवलपर द्वारा भावी परिवर्तन के मामले में उन्हें वहां छोड़ दें? –

+1

@Eric, आमतौर पर आप 'assert' मैक्रो का उपयोग करते हैं जो स्वचालित रूप से रिलीज के लिए इसे बनाते समय कोड के रिक्त ब्लॉक पर संकलित हो जाता है। फिर उनसे छुटकारा पाने का कोई कारण नहीं है, वे किसी भी व्यक्ति के लिए उपयोगी होंगे जो कोड को संशोधित करता है। वे दस्तावेज के रूप में भी कार्य करते हैं। –

0

आपके द्वारा उल्लिखित डीबगिंग के लिए आवेषण उपयोगी हैं। उन्हें इसे कभी भी उत्पादन कोड में नहीं बनाना चाहिए (संकलित के रूप में, उन्हें निश्चित रूप से #ifdefs में लपेटना ठीक है)

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

void f(int *p) 
{ 

    if (!p) 
    { 
    do_error("FATAL, P is null."); 
    } 

    p->do(); 
} 

कहाँ do_error एक समारोह है कि एक त्रुटि लॉग करता है और सफाई से बाहर निकल जाता है है।

2

रक्षात्मक प्रोग्रामिंग हमेशा सर्वोत्तम होती है। आपको हमेशा यह मानना ​​चाहिए कि आपके सभी परीक्षणों के बावजूद, आपका आवेदन बग के साथ भेज देगा।इस प्रकार, यह उन स्थितियों में नल चेक जोड़ने के लिए आपके सर्वोत्तम हितों में है जहां आप एक पूर्ण सूचक सम्मान से बच सकते हैं और बस आगे बढ़ सकते हैं।

हालांकि, ऐसी परिस्थितियां हैं जहां दुर्घटना से बचने के लिए कोई आसान तरीका नहीं है, और उन मामलों में, जोर आपके विकास चक्र के दौरान समस्या का पता लगाने का एकमात्र तरीका है।

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

+0

ऊपर। मैं आपके विचार से सहमत हूं कि कभी-कभी अच्छी UI अधिसूचना वाले प्रोग्राम को क्रैश करना बिना किसी सूचना के खराब स्थिति में चलाने से बेहतर होता है। –

+0

@Eric: यदि आप यह निर्धारित कर सकते हैं कि प्रोग्राम "खराब स्थिति" में है, तो आप इसे (* उदा। * UI अधिसूचना के साथ) संभाल सकते हैं। एक * assert * इस मामले के लिए __not__ आवश्यक है, अपवाद फेंकने या त्रुटि-हैंडलिंग कोड सहित बस ठीक होगा। इसके अलावा, यदि आप 100% नहीं मानते हैं कि इस तरह के राज्य में कार्यक्रम के लिए असंभव * है, * जोर * सही निर्माण नहीं है - आपको फिर से राज्य का परीक्षण करना चाहिए और या तो अपवाद फेंकना चाहिए या त्रुटि को संभाल लें। * जोर * यह नहीं कहता है "मैं आशा करता हूं * यह सच है", यह कहता है, "मैं * जोर देता हूं * यह (जरूरी) सच है"। – user359996

+0

आप एक बुरी स्थिति का पता लगा सकते हैं, लेकिन आप इसे से पुनर्प्राप्त नहीं कर सकते हैं। यदि किसी चर के पास एक मान है, तो संभवतः यह नहीं होना चाहिए, आप इससे कैसे ठीक हो जाते हैं? सही मूल्य का अनुमान लगाओ? यह एक संकेत है कि कुछ और पूरी तरह टूटा जा सकता है जो इस चर को खराब कर देता है। शायद स्मृति भी मिटा दिया। आप इससे ठीक नहीं हो सकते हैं। इसके अलावा, प्रदर्शन कारणों से, आप रिलीज बिल्ड में बहुत समय त्रुटि-जांच खर्च नहीं करना चाहते हैं। (मेरी आवश्यकताएं शायद आपके से अलग हैं, मैं ज्यादातर खेल कर रहा हूं - प्रत्येक शाखा में कुछ मूल कार्यों में गिना जाता है।) – EboMike

0

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

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

1

कड़ाई से बोलते हुए, दूसरे कोड में अनावश्यकता है।

void f(int *p) 
{ 
    assert(p); 
    if (p) // Beats the purpose of assertion 
    { 
    p->do(); 
    } 
} 

दावा का मतलब है कि त्रुटि हुई है। कुछ जो अप्रत्याशित/अनचाहे है। उपरोक्त कोड में, या तो

1) आप ठीक से उस मामले को संभालने में सक्षम हैं जहां पी शून्य है। (पी-> डू()) को कॉल न करके - जो माना जाता है कि सही/अपेक्षित चीज है। हालांकि, फिर दावा झूठा अलार्म है।

2) दूसरी तरफ, यदि पी-> डू() को कॉल नहीं कर रहा है, तो कुछ गलत हो जाएगा (शायद कोड में या आउटपुट में), तो दावा सही है, लेकिन कोई बिंदु नहीं होना चाहिए वैसे भी जारी है।

उपर्युक्त कोड में प्रोग्रामर उन मामलों को संभालने के लिए अतिरिक्त मेहनत कर रहा है जो किसी भी तरह से गलत हैं।

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

0

के बाद से बहुत से लोगों को रिलीज़ मोड में दावे डाल पर टिप्पणी कर रहे हैं:

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

एक उदाहरण जहां रिलीज कोड आवेषण अच्छे हैं - यदि तर्क को कोड की एक विशेष शाखा को मारना नहीं है। इस मामले में, जोर दें (0) ठीक है [इस प्रकार किसी भी प्रकार का जोर (0) हमेशा रिलीज कोड में छोड़ा जा सकता है]।

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