जब मैं कुछ भी नहीं तोड़ने के लिए यह सुनिश्चित करने के लिए एक बड़ी विधि को फिर से बनाने में क्या मदद मिलेगी?


10

मैं वर्तमान में किसी भी यूनिट परीक्षण के साथ एक बड़े कोडबेस के एक हिस्से को फिर से बना रहा हूं। मैंने ब्रूट तरीके से कोड को रीफ़ैक्टर करने की कोशिश की, यानी कोड क्या कर रहा है और क्या बदलाव होता है, इसका अनुमान लगाने की कोशिश करने से इसका अर्थ नहीं होगा, लेकिन सफलता के बिना: यह कोडबस के चारों ओर बेतरतीब ढंग से सुविधाओं को तोड़ता है।

ध्यान दें कि रीफैक्टरिंग में लिगेसी सी # कोड को एक अधिक कार्यात्मक शैली में शामिल करना शामिल है (विरासत कोड .NET फ्रेमवर्क 3 की सुविधाओं में से किसी का उपयोग नहीं करता है और बाद में LINQ सहित), जेनेरिक को जोड़ते हुए जहां कोड उनसे लाभ उठा सकता है, आदि।

मैं औपचारिक तरीकों का उपयोग नहीं कर सकता , यह देखते हुए कि उनकी लागत कितनी होगी।

दूसरी ओर, मैं मानता हूं कि कम से कम "कोई भी रिफैक्टेड विरासत कोड यूनिट परीक्षणों के साथ आएगा" नियम का कड़ाई से पालन किया जाना चाहिए, चाहे कितना भी खर्च हो। समस्या यह है कि जब मैं 500 एलओसी निजी पद्धति का एक छोटा हिस्सा रिफ्लेक्टर करता हूं, तो यूनिट परीक्षण जोड़ना एक कठिन काम प्रतीत होता है।

किसी दिए गए कोड के लिए कौन से यूनिट परीक्षण प्रासंगिक हैं, यह जानने में मेरी क्या मदद कर सकते हैं? मैं यह अनुमान लगा रहा हूं कि कोड का स्थैतिक विश्लेषण किसी तरह मददगार होगा, लेकिन वे कौन से उपकरण और तकनीक हैं जिनका मैं उपयोग कर सकता हूं:

  • मुझे पता है कि मुझे कौन सी इकाई परीक्षण बनाने चाहिए,

  • और / या पता है कि क्या मैंने जो परिवर्तन किया है वह मूल कोड को इस तरह से प्रभावित करता है कि वह अब से अलग तरीके से निष्पादित हो रहा है?


आपका क्या तर्क है कि इकाई परीक्षण लिखने से इस परियोजना के लिए समय बढ़ जाएगा? कई प्रस्तावक असहमत होंगे, लेकिन उन्हें लिखने की आपकी क्षमता पर यह भी आकस्मिक है।
जेएफओ

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

1
आप formal methods in software developmentवैसे भी उपयोग नहीं करना चाहेंगे क्योंकि यह एक प्रोग्राम की शुद्धता को सही तर्क का उपयोग करने के लिए साबित करने के लिए उपयोग किया जाता है और एक बड़े कोडबेस को पुनःप्राप्त करने के लिए प्रयोज्यता नहीं होगी। आमतौर पर चिकित्सा अनुप्रयोगों जैसे क्षेत्रों में कोड कार्यों को सही ढंग से साबित करने के लिए उपयोग किए जाने वाले औपचारिक तरीके। आप सही हैं यह करना महंगा है यही कारण है कि इसका उपयोग अक्सर नहीं किया जाता है।
मुशी

ReSharper में रिफ्लेक्टर विकल्प जैसे एक अच्छा उपकरण इस तरह के काम को बहुत आसान बना देता है। इस तरह की स्थितियों में यह अच्छी तरह से पैसे के लायक है।
billy.bob

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

जवाबों:


12

मेरे पास भी ऐसी ही चुनौतियां हैं। विरासत कोड के साथ काम कर रहे पुस्तक एक महान संसाधन है, लेकिन वहाँ एक धारणा है कि आप इकाई परीक्षण में जूता-सींग अपने काम का समर्थन करने के कर सकते हैं। कभी-कभी यह संभव नहीं है।

मेरे पुरातत्व कार्य में (इस तरह से विरासत कोड पर रखरखाव के लिए मेरा शब्द), मैं एक समान दृष्टिकोण का पालन करता हूं जो आपने उल्लिखित किया था।

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

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

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

संक्षेप में, मेरा दृष्टिकोण आपके द्वारा रखी गई बातों के समान है। यह बहुत काम है; फिर परिधि, व्यक्तिगत परिवर्तन करें; और फिर सत्यापित करें, सत्यापित करें, सत्यापित करें।


2
अकेले "पुरातत्व" के उपयोग के लिए +1। यही शब्द मैं इस गतिविधि का वर्णन करने के लिए उपयोग करता हूं और मुझे लगता है कि इसे लगाने का एक शानदार तरीका है (यह भी सोचा कि उत्तर अच्छा था - मैं वास्तव में उथले नहीं हूं)
एरिक डायट्रिच

10

जब मैं कुछ भी नहीं तोड़ने के लिए यह सुनिश्चित करने के लिए एक बड़ी विधि को फिर से बनाने में क्या मदद मिलेगी?

संक्षिप्त उत्तर: छोटे कदम।

समस्या यह है कि जब मैं 500 एलओसी निजी पद्धति का एक छोटा सा हिस्सा रिफ्लेक्टर करता हूं, तो यूनिट परीक्षणों को जोड़ना एक कठिन काम प्रतीत होता है।

इन चरणों पर विचार करें:

  1. कार्यान्वयन को एक अलग (निजी) फ़ंक्शन में ले जाएं और कॉल को प्रत्यायोजित करें।

    // old:
    private int ugly500loc(int parameters) {
        // 500 LOC here
    }
    
    // new:    
    private int ugly500loc_old(int parameters) {
        // 500 LOC here
    }
    
    private void ugly500loc(int parameters) {
        return ugly500loc_old(parameters);
    }
    
  2. सभी इनपुट और आउटपुट के लिए अपने मूल कार्य में लॉगिंग कोड (सुनिश्चित करें कि लॉगिंग विफल नहीं होता है) जोड़ें।

    private void ugly500loc(int parameters) {
        static int call_count = 0;
        int current = ++call_count;
        save_to_file(current, parameters);
        int result = ugly500loc_old(parameters);
        save_to_file(current, result); // result, any exceptions, etc.
        return result;
    }
    

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

  3. अब आपके पास max(call_count)अपने परीक्षण लिखने के लिए इनपुट और आउटपुट के सेट हैं ; आप एक भी परीक्षण लिख सकते हैं जो आपके सभी मापदंडों / परिणाम सेटों पर निर्भर करता है और आपके पास उन्हें लूप में निष्पादित करता है। आप एक विशेष परीक्षा (विशेष i / o सेट से गुजरने के लिए जल्दी से जाँच करने के लिए उपयोग की जाने वाली) के लिए एक सशर्त परीक्षण भी लिख सकते हैं।

  4. // 500 LOC hereअपने ugly500locफ़ंक्शन में वापस जाएं (और लॉगिंग कार्यक्षमता को हटा दें)।

  5. बड़े फ़ंक्शन से फ़ंक्शंस निकालना शुरू करें (और कुछ नहीं, बस फ़ंक्शंस निकालें) और परीक्षण चलाएं। इसके बाद आपके पास रिफ्लेक्टर के लिए 500LOC एक के बजाय अधिक छोटे कार्य होने चाहिए।

  6. इसके बाद हमेशा खुश रहें।


3

आमतौर पर यूनिट टेस्ट जाने का तरीका है।

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

किसी दिए गए कोड के लिए कौन से यूनिट परीक्षण प्रासंगिक हैं, यह जानने में मेरी क्या मदद कर सकते हैं?

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

तब आप बिना किसी समस्या के सभी को फाड़ सकते हैं।

AFAIK, इसके लिए कोई बुलेट प्रूफ तकनीक नहीं है ... आपको सिर्फ मैथडिकल (जिस भी विधि में आप सहज महसूस करते हैं) होना चाहिए, बहुत समय और बहुत धैर्य! :)

चियर्स और गुड लक!

एलेक्स


कोड कवरेज टूल यहां आवश्यक हैं। यह पुष्टि करना कि आपने निरीक्षण के माध्यम से एक बड़े जटिल तरीके से हर पथ को कवर किया है। एक उपकरण जो दिखाता है कि सामूहिक रूप से KitchenSinkMethodTest01 () ... KitchenSinkMethodTest17 () कवर लाइनें 1-45, 48-220, 245-399 और 488-500 है, लेकिन बीच के कोड को स्पर्श न करें; यह पता लगाना होगा कि आपको अधिक सरल लिखने के लिए किन अतिरिक्त परीक्षणों की आवश्यकता है।
दान
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.