2015-08-18 6 views
5

अपवाद बनाम जोर से पहले यहां पूछा गया है: Design by contract using assertions or exceptions?, Assertion VS Runtime exception, C++ error-codes vs ASSERTS vs Exceptions choices choices :(, Design by contract using assertions or exceptions?, आदि (*) हर्ब सटर के कोडिंग मानकों की तरह किताबें भी हैं जो इस बारे में बात करती हैं। सामान्य सर्वसम्मति यह प्रतीत होती है:एक वैज्ञानिक कंप्यूटिंग लड़के के लिए अपवाद बनाम बनाम (मैं अपने कोड का एकमात्र उपयोगकर्ता हूं)?

आंतरिक त्रुटियों के लिए दावे का उपयोग करें, इस अर्थ में कि मॉड्यूल और डेवलपर का उपयोगकर्ता एक और एक ही व्यक्ति/टीम है। बाकी सब कुछ के लिए अपवाद का प्रयोग करें। (**)

यह नियम मुझे एक चीज़ को छोड़कर, मुझे बहुत समझ में आता है। मैं वैज्ञानिक सिमुलेशन के लिए सी ++ का उपयोग कर एक वैज्ञानिक हूं। मेरे विशेष संदर्भ में, इसका मतलब है कि मैं अपने अधिकांश कोड का एकमात्र उपयोगकर्ता हूं। अगर मैं इस नियम को लागू करता हूं, तो इसका मतलब है कि मुझे कभी अपवादों का उपयोग नहीं करना पड़ेगा? मुझे नहीं लगता, उदाहरण के लिए, अभी भी I/O त्रुटियां हैं, या स्मृति आवंटन समस्याएं हैं, जहां अपवाद अभी भी आवश्यक हैं। लेकिन "बाहरी दुनिया" के साथ मेरे कार्यक्रम की उन बातचीत के अलावा, क्या ऐसे अन्य परिदृश्य हैं जहां मुझे अपवादों का उपयोग करना चाहिए?

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

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

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

+0

क्या आप कभी भी इस कोड में से किसी एक को साझा नहीं करते हैं/इसे पुस्तकालय बनाते हैं या किसी और को किसी भी समय इस कोड को लेना होगा? आपको कोड को यथासंभव पोर्टेबल बनाए रखने की कोशिश करनी चाहिए – NathanOliver

+0

@NathanOliver निकट भविष्य में नहीं। मैं इसे छात्रों, या करीबी सहयोगियों के साथ साझा करता हूं। लेकिन जैसा कि आप कहते हैं, मुझे रखरखाव की परवाह है। हालांकि, हर्ब सटर के नियम को लागू करने के लिए, मुझे अपने कोड में मनमानी रेखाएं खींचना है, यह निर्धारित करने के लिए कि किसी दिए गए मॉड्यूल में "आंतरिक" क्या है, और बाहरी क्या है। मुझे वास्तव में इसके लिए कोई उपयोग नहीं मिला है। – becko

+0

ऐतिहासिक रूप से आवेषण का उपयोग एक 'सी' तकनीक है। अपवादों का उपयोग करना एक 'सी ++' तकनीक है। इससे आपके उद्देश्य के बारे में आपकी सोच में कोई फर्क पड़ सकता है। आवेषणों का उपयोग ऐसी परिस्थितियों का पता लगाने के लिए किया जाना चाहिए जो संभवतः कभी नहीं हो सकते हैं। लेकिन अगर ऐसा होता है तो मैं जानना चाहता हूं कि मैं कोड डीबग कर सकता हूं। –

उत्तर

0

मैं उन दावों का उपयोग करता हूं जहां मैं अपेक्षा करता हूं कि चेक का प्रदर्शन प्रभाव हो। अर्थात। सरल प्रकारों के वेक्टर या मैट्रिक्स वर्ग को लिखते समय (उदा। double, complex<double>), और मैं एक सीमा जांच करना चाहता था, मैं assert() का उपयोग करता हूं, क्योंकि चेक में संभावित रूप से बड़े प्रदर्शन प्रभाव होते हैं, क्योंकि यह प्रत्येक तत्व पहुंच के साथ होता है। मैं -DNDEBUG के साथ उत्पादन में इस चेक को बंद कर सकता हूं।

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

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

// This assert macro does not depend on the value of NDEBUG 
#define assert_always(expr)           \ 
    do                 \ 
    {                 \ 
    if(!(expr))              \ 
    {                \ 
     std::cerr << __FILE__ << ":" << __LINE__ << ": assert_always(" \ 
       << #expr << ") failed" << std::endl;     \ 
     std::abort();             \ 
    }                \ 
    } while(false) 

(यह उदाहरण एक संशोधित नाम के साथ here से लिया गया है थोड़ा व्यापक उद्देश्य से संकेत मिलता है)।

+0

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

+1

@stijn मैंने मैक्रो को शामिल करने के उत्तर को अपडेट किया जैसा आपने तीसरे तरीके से कहा था। –

+0

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

1

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

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

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

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

+1

मुझे यह भेद पसंद है कि एक जोर से संकेत देना चाहिए "कोडिंग (और संभवतः डिबगिंग) आवश्यक है" जबकि एक अपवाद का मतलब है कि कोड ठीक है, डेटा तोड़ दिया गया है। –

4

assert() प्रोग्रामर गलतियों के खिलाफ एक सुरक्षा है, जबकि अपवाद बाकी अस्तित्व के खिलाफ सुरक्षा हैं।

एक उदाहरण के साथ इस बारे में बताएं:

double divide(double a, double b) { 
    return a/b; 
} 

इस समारोह के स्पष्ट समस्या यह है कि अगर == 0 ख, तो आपको एक त्रुटि मिलेगा।

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

double divide(double a, double b) { 
    ASSERT(b != 0); 
    return a/b; 
} 

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

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

अब, यदि आपके पास फ़ंक्शन को पास किए गए मानों पर कोई नियंत्रण नहीं है तो क्या होता है? दावा केवल किसी भी सुरक्षा के बिना कार्यक्रम के प्रवाह को बाधित करेगा।

double divide(double a, double b) { 
    ASSERT(b != 0); 
    if (b == 0) 
     throw DivideByZeroException(); 
    return a/b; 
} 

try { 
    result = divide(num, user_val); 
} catch (DivideByZeroException & e) { 
    display_informative_message_to_user(e); 
} 

ध्यान दें कि अभिकथन जगह में अब भी है, क्योंकि यह क्या गलत हो सकता है की सबसे अधिक पठनीय संकेत है:

करने के लिए समझदार बात यह है। अपवाद के अतिरिक्त, हालांकि, आपको समस्या से अधिक आसानी से पुनर्प्राप्त करने की अनुमति देता है।

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

अब

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

तो, यदि आप सुरक्षित रहना चाहते हैं और विकास के दौरान और सामान्य निष्पादन के दौरान गलतियों के जोखिम को कम करना चाहते हैं, तो आप कभी भी सावधान नहीं रह सकते हैं, और दोनों तंत्र को पूरक तरीके से प्रदान करना चाहते हैं।

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