क्या सांत्वना / मुद्रण एक अच्छी डिबगिंग रणनीति है?


11

मान लीजिए कि हमारे पास एक फंक्शन है:

public void myStart()
{
    for (int i = 0; i<10; i++) myFunction(i); 
}


private int myFunction(int a)
{

    a = foo(a);
    a = bar(a);
    return a; 
}

private int foo(int a)
{
    //do something here

    //something gnarly here

    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

अब जो भी कारण हो, हमारा कोड काम नहीं कर रहा है। शायद यह एक त्रुटि फेंक रहा है, शायद यह गलत मान लौटा रहा है, शायद यह एक अनंत लूप में फंस गया है।

पहली बात यह है कि किसी भी प्रथम वर्ष के प्रोग्रामर, कंसोल / एसटीडी से प्रिंट आउट है, (डिबगर का उपयोग करना सीखने से पहले हैलो वर्ल्ड को प्रिंट करना सीखें)।

उदाहरण के लिए इस कोड को डीबग करने के लिए वे निम्नलिखित कार्य कर सकते हैं:

private int myFunction(int a)
{
    print("before foo: a=" + a); 
    a = foo(a);
    print("before bar: a=" + a);
    a = bar(a);

    return a; 
}

private int foo(int a)
{
    //do something here
    print ("foo step1: a=" + a); 

    //something gnarly here
    print ("foo step2: a=" + a + " someOtherValue="+ someOtherValue + " array.length= " + someArray.length()); 
    //etc
    return aValue;
}

private int bar(int a)
{
    // do something here
    //return aValue;
}

अब वे कोड चलाते हैं, उन्हें एक बड़ा कंसोल प्रिंट आउट मिलता है, जिसे वे ट्रेस कर सकते हैं जहां चीजें गलत हो रही हैं।

पाठ्यक्रम का एक विकल्प, प्रत्येक बिंदु पर कोड के माध्यम से ब्रेकपॉइंट सेट करना और चरणबद्ध करना है।

कंसोल को प्रिंट करने का एक प्रमुख लाभ यह है कि डेवलपर एक चरण में मानों के प्रवाह को देख सकता है, बिना चरणों आदि पर क्लिक किए।

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

(क्या यह संभव है कि डिबगर को केवल कुछ मानों को एक लॉग में प्रिंट करने के लिए कहा जाए ?, ब्रेकपॉइंट्स को आसानी से जोड़ा जा सकता है या वास्तव में कोड को संशोधित किए बिना हटाया जा सकता है।)

मैं अभी भी एक प्राथमिक डीबगिंग विधि के रूप में कंसोल प्रिंटिंग का उपयोग करता हूं, मैं सोच रहा हूं कि यह किसी अन्य चीज की तुलना में कितना सामान्य / प्रभावी है।


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

7
डिबगर्स का उपयोग करना सीखना महत्वपूर्ण है, हालांकि, ऐसी कई परिस्थितियां हैं जिनसे आप सामना कर सकते हैं जहां प्रिंटफ डीबगिंग एकमात्र डिबगिंग विधि उपलब्ध है।
whatsisname

जवाबों:


26

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

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

तो, अपने विशिष्ट प्रश्न का उत्तर देने के लिए। हाँ। निष्पादन का पता लगाने के लिए प्रिंट का उपयोग करना अच्छा है और व्यापक रूप से डिबगिंग रणनीति का उपयोग किया जाता है। तथापि...

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

लॉगिंग फ़्रेमवर्क का उपयोग कर रहा है ...

  1. आपके द्वारा किए जाने के बाद आपको सभी प्रिंट हटाने की आवश्यकता नहीं होगी।
  2. आपके द्वारा कोड में छोड़े गए प्रिंट, आपको या किसी अन्य डेवलपर को डिबग करने में मदद कर सकते हैं जो भविष्य में उसी कोड का उपयोग करता है
  3. आप बिना हटाए गए प्रिंट को जोड़ने के लिए हर बार इसे फिर से बनाए बिना इस कोड को फ़ील्ड में डीबग कर पाएंगे।
  4. आप केवल सांत्वना ही नहीं, बल्कि कहीं भी लॉगिंग संदेशों को पुनर्निर्देशित कर सकेंगे। वे एक फाइल, syslog, DB, सॉकेट ... आदि में जा सकते थे

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


पहले पैराग्राफ के लिए +1। डिबगर और लॉग दो अलग-अलग समस्याओं को हल करते हैं।
ब्लरफाल

1
लेकिन क्या आप इस बात से सहमत नहीं हैं कि कोड स्टेटमेंट में लॉग स्टेटमेंट को छोड़ना इसे खत्म कर देता है?
dwjohnston

1
निर्भर करता है कि आप किस तरह के लॉग स्टेटमेंट छोड़ते हैं। मैंने अभी पाया और इसे हटा दिया: "logger.error (" WHAT ")"। अन्यथा, मैं अपने बाकी कोड की तरह ही लॉगिंग कोड का इलाज करता हूं। इसे प्रारूपित करें, यह अच्छा लग रहा है और इसे जानकारीपूर्ण बनाते हैं। हाँ, हर दूसरी पंक्ति में एक प्रिंट स्टेटमेंट छिड़कना बहुत अधिक है और कई बार मुझे इसका सहारा लेना पड़ा। लेकिन आम तौर पर, पूरी फ़ाइल में 10-20 लॉग स्टेटमेंट (फाइलें / कक्षाएं यथोचित आकार और विशाल नहीं होती हैं) खराब नहीं होती हैं।
डीएक्सएम

मुझे लगता है कि कुछ लॉग बयान छोड़ने उपयोगी हो सकता है, उदाहरण के लिए यदि आप एक उत्पादन प्रणाली आप के रूप में वे ऐसा इस्तेमाल कर रहे हैं विभिन्न महत्वपूर्ण चर लॉग कर सकते हैं अगर कुछ त्रुटि मिलती है पैदा आप देख सकते हैं अपने उत्पादन में तुरंत क्या हुआ वातावरण। हालांकि, विकास के संदर्भ में यह गड़बड़ है। उदाहरण के लिए, आप अपना पार्सिंग फ़ंक्शन लिख रहे हैं, और आपको अपना regex सही नहीं मिला है - इसलिए आप लॉग स्टेटमेंट की एक श्रृंखला में डालते हैं, बस यह जांचने के लिए कि क्या चल रहा है, और अंततः इसे छाँट लें। मुझे नहीं लगता कि यह उन्हें छोड़ने के लिए आगे जाने के लिए मूल्य जोड़ता है।
dwjohnston

1
@ इज़काता: यह सब आपके विशिष्ट बग की बारीकियों पर और आपके कोड को पहले से ही लॉग इन करने पर निर्भर करेगा। बिंदु जो मैं प्राप्त करने की कोशिश कर रहा हूं वह यह है कि लॉगिंग स्टेटमेंट्स और उन्हें विभिन्न स्तरों पर रखने का हमेशा मूल्य होता है: ERR -> WARN ... -> DEBUG। यदि आपको किसी बहुत विशिष्ट चीज़ के लिए और अधिक की आवश्यकता है, तो निश्चित रूप से प्रिंट स्टेटमेंट जोड़ना शुरू करें। लेकिन एक लॉगिंग स्टेटमेंट के रूप में "प्रिंट" का उपयोग करने वाले किसी व्यक्ति के लिए मेरा जवाब, हमेशा एक रूपरेखा पर स्विच किया जाएगा और उसका उपयोग करना शुरू होगा।
DXM

3

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

डिबगर्स के लाभ:

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

प्रवेश / मुद्रण के लाभ:

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

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

1

एक तरह से मानक आउटपुट पर मुद्रण आपके कोड को डिबग करने के लिए एक अच्छी रणनीति हो सकती है, उदाहरण के लिए

  • मैं अपने कोड के विभिन्न स्तरों पर क्या हो रहा है यह देखने के लिए बहुत सारे प्रिंट स्टेटमेंट का उपयोग करता हूं, खासकर अगर मैं पूरी तरह से त्रुटि नहीं समझता हूं

  • या हो सकता है कि त्रुटि में कोई विस्तृत जानकारी न हो जो मुझे बताए कि कोड का कौन सा भाग वास्तव में समस्या पैदा कर रहा है।

हालाँकि, आपको डीबगिंग टूल के लिए उपयोग करने की आवश्यकता है, वहाँ बहुत सारे हैं जो आप किस भाषा या प्लेटफ़ॉर्म के आधार पर उपयोग करते हैं।

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


3
यह पोस्ट पढ़ना मुश्किल है (पाठ की दीवार)। क्या आप इसे बेहतर आकार में संपादित करेंगे ?
जन्नत

मैंने इसे थोड़ा पठनीय बना दिया। पिछले के लिए क्षमा करें!
प्लायिक्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.