रीफैक्टरिंग क्या है और केवल संशोधित कोड क्या है?


81

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

मैं तरीकों को निकालने और कक्षाओं के नाम बदलने जैसी चीज़ों को वापस लेने पर विचार करता हूं। उन्होंने डेटा संरचनाओं को बदलने (जैसे जावा LinkedListसे ए ArrayList), एल्गोरिदम को बदलने (बबल सॉर्ट के बजाय मर्ज सॉर्ट का उपयोग करने), और यहां तक ​​कि रीफ़ैक्टरिंग के रूप में कोड के बड़े हिस्से को फिर से लिखने जैसी चीजों का भी सुझाव दिया ।

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

जवाबों:


77

मार्टिन फाउलर का "रिफ़ैक्टरिंग: एक्ज़िस्टेंस कोड के डिज़ाइन में सुधार" शायद यह संदर्भ है:

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

यूनिट टेस्टिंग के साथ रिफैक्टिंग हाथ से हाथ जाती है। रिफ्लेक्टर से पहले परीक्षण लिखें और फिर आपके पास रिफैक्टरिंग में एक आत्मविश्वास का स्तर है (परीक्षणों के कवरेज के अनुपात में)।

एक अच्छा संदर्भ है: रिफैक्टरिंग के बारे में जानकारी


16
फाउलर उद्धरण निश्चित रूप से प्रासंगिक है, और हाँ, यह यूनिट परीक्षणों के साथ हाथ से जाता है ... लेकिन, क्या यह वास्तव में पूछे गए सवालों का जवाब देता है: क्या उदाहरणों का उल्लेख रिफैक्टिंग या सिर्फ संशोधित कोड है? कौन सही है, ओपी या उनके सहयोगी, और क्यों?
जोनिक

36

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

यदि हम एक रीफैक्टरिंग, या व्यवहार-संरक्षण कोड संशोधन कर रहे हैं:

  • हमारे सभी यूनिट परीक्षणों को संशोधन से पहले और बाद में पास करना चाहिए
  • हमें किसी भी परीक्षण को संशोधित करने या किसी भी नए को लिखने की आवश्यकता नहीं है
  • जब हम किया जाता है तो हम क्लीनर कोड की उम्मीद करते हैं
  • हम नए व्यवहार की उम्मीद नहीं करते हैं

यदि हम एक व्यवहार-परिवर्तन कोड संशोधन कर रहे हैं:

  • हम नए व्यवहार की उम्मीद करते हैं
  • हमें नए परीक्षण लिखने चाहिए
  • जब हमें किया जाता है तो हमें डर्टियर कोड मिल सकता है (और फिर इसे रिफ्लेक्टर करना चाहिए)

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


3
+1, बिल्कुल। विशेष रूप से आपके द्वारा दिया गया औचित्य; muddled उम्मीदों। अपना उत्तर लिखते समय, मेरे मन में यह था, भले ही मैं इसे बड़े करीने से लिखने में असफल रहा हो :)
जोनिक

18

मेरा विचार देने के लिए:

छोटे, वृद्धिशील परिवर्तन जो कोड को एक बेहतर स्थिति में छोड़ते हैं, यह पाया गया था

निश्चित रूप से हाँ: "कॉस्मेटिक" परिवर्तन जो सीधे तौर पर सुविधाओं से संबंधित नहीं हैं (अर्थात यह परिवर्तन अनुरोध के रूप में बिल योग्य नहीं है)।

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

निश्चित रूप से हो सकता है: डेटा संरचनाओं और एल्गोरिदम को बदलना कुछ हद तक सीमा का मामला है। यहां निर्णय लेने का अंतर IMO के छोटे चरण हैं: वितरित करने के लिए तैयार रहें, किसी अन्य मामले पर काम करने के लिए तैयार रहें।


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

पुनर्लेखन का मतलब होगा मॉड्यूल को दूर फेंकना एक बेहतर और तेजी से खरोंच से एक इमारत, बस पुराने से कुछ टुकड़े चुनना। या एक नया कोर लिखना, फिर इसे मौजूदा संवाद में फिट करना।

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


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

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

कंकड़ की दीवार की तरह जहां हर रोज जमीन पर गिरता है। और रोज एक राहगीर उसे उठाकर वापस रख देता है।


12

मार्टिन फाउलर की परिभाषा को ध्यान में रखते हुए,

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

... मुझे लगता है कि आप स्पष्ट रूप से सही हैं।

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

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

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


3
मुझे यकीन नहीं है कि कोड बनाना तेजी से बाहरी व्यवहार में बदलाव के रूप में योग्य हो जाता है ...
गांगेय कॉव्बॉय

2
हाँ, मैं आपकी बात देख रहा हूँ, मुझे लगता है कि यह निर्भर करता है कि आप इसे किस कोण से देखते हैं। :) किसी भी मामले में, IMO, जब आपको प्रोग्रामिंग पर ध्यान देना चाहिए कि आप किस "टोपी" को हर पल पहन रहे हैं, यानी आप वास्तव में क्या हासिल करना चाह रहे हैं। दूसरे शब्दों में, आपको सचेत रूप से अलग होना चाहिए जब आप किसी फीचर को जोड़ रहे हैं / ठीक कर रहे हैं, जब रीफैक्टरिंग कर रहे हैं, और जब अनुकूलन (प्रयासों को बेहतर बना रहे हैं)। IIRC, फाउलर भी रिफैक्टिंग पर अपनी निश्चित पुस्तक में इस बारे में बात करते हैं।
जोनिक

1
बाहरी परिवर्तन भाग के लिए, हम यह कहने के लिए फिर से तैयार कर सकते हैं: [...] अपने बाहरी व्यवहार को बदलने के बिना अगर व्यवहार महत्व का है। यदि प्रदर्शन या तो महत्वपूर्ण है (तेजी से या धीमा), तो एक परिवर्तन न करें जो इसे आपके "रीफैक्टरिंग" चरण के हिस्से के रूप में प्रभावित कर सकता है।
लोकी

11

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

Refactoring के लिए विशिष्ट मामला है

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

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


7

मुझे लगता है कि आप सही हैं, लेकिन किसी शब्द के अर्थ पर बहस करना विशेष रूप से दिलचस्प या उत्पादक नहीं है।


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

4

http://en.wikipedia.org/wiki/Code_refactoring

कोड रीफैक्टरिंग एक कंप्यूटर प्रोग्राम की आंतरिक संरचना को उसके बाहरी कार्यात्मक व्यवहार या मौजूदा कार्यक्षमता को संशोधित किए बिना बदलने की प्रक्रिया है, सॉफ्टवेयर के आंतरिक गैर-कार्यात्मक गुणों में सुधार करने के लिए, उदाहरण के लिए, कोड पठनीयता में सुधार करने के लिए, कोड संरचना को सरल बनाने के लिए, कोड को बदलने के लिए। किसी दिए गए प्रोग्रामिंग प्रतिमान का पालन करने के लिए, स्थिरता में सुधार करने के लिए, प्रदर्शन में सुधार करने के लिए, या एक्स्टेंसिबिलिटी में सुधार करने के लिए।

मैं मानता हूं कि रिफैक्टिंग कोड में मौजूदा कोड को तोड़ना शामिल है। बस सुनिश्चित करें कि आपके पास इकाई परीक्षण हैं ताकि आप किसी भी बग का परिचय न दें, और बाकी कोड संकलित करें। Resharper जैसे C # के लिए रीफैक्टरिंग टूल्स का उपयोग करना इसे इतना आसान बना देता है!

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

3

मैं असहमत हूं :

सॉफ्टवेयर इंजीनियरिंग में, "रीफैक्टरिंग" स्रोत कोड का अर्थ है कि इसके समग्र परिणामों को बदले बिना इसमें सुधार करना [...]

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


1

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

यदि यह एक विधि है तो नाम, इनपुट तर्क, लौटाए गए मान का प्रकार और संभवतः दिए गए कथनों को नियत रखें। विधि के अंदर सभी परिवर्तनों को लागू करें बिना यह देखे कि इसे बाहर कैसे देखा जाए।

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

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


0

क्रियाशील करना = क्रियात्मक लोगों को अनछुए रखते हुए गैर-कार्यात्मक आवश्यकताओं में सुधार करना।

गैर-कार्यात्मक आवश्यकताएं = प्रतिरूपकता, परीक्षणशीलता, स्थिरता, पठनीयता, चिंताओं को अलग करना, लिस्कोव सिद्धांतों और इतने पर ...

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