क्या गुणवत्ता में सुधार की उम्मीद में यह मिनी-रिफलेक्टर कोड के लिए उपयोगी है, या क्या यह "लाभ के बिना" के आसपास "केवल कोड घूम रहा है"?


12

उदाहरण

मैं एक ही स्थान पर "सब कुछ" करता है जो मोनोलिथिक कोड में आया था - डेटाबेस से डेटा लोड करना, HTML मार्कअप दिखाना, राउटर / कंट्रोलर / एक्शन के रूप में कार्य करना। मैंने अपनी फ़ाइल में SRP मूविंग डेटाबेस कोड लागू करना शुरू किया, चीजों के लिए बेहतर नामकरण प्रदान किया, और यह सब अच्छा लग रहा था, लेकिन फिर मुझे संदेह होने लगा कि मैं ऐसा क्यों कर रहा हूं।

रिफ्लेक्टर क्यों? उद्देश्य क्या है? क्या यह बेकार है? क्या फायदा है? ध्यान दें कि मैंने ज्यादातर मोनोलिथिक फ़ाइल को छोड़ दिया है, लेकिन केवल उस छोटे हिस्से को फिर से सक्रिय किया है जो उस क्षेत्र के लिए प्रासंगिक था जहां मुझे कुछ काम करने की आवश्यकता थी।

मूल कोड:

एक ठोस उदाहरण देने के लिए, मैं इस कोड स्निपेट में आया था - यह उत्पाद विनिर्देशों को ज्ञात उत्पाद आईडी या उपयोगकर्ता द्वारा चयनित संस्करण आईडी द्वारा लोड करता है:

if ($verid)
    $sql1 = "SELECT * FROM product_spec WHERE id = " . clean_input($verid);
else
    $sql1 = "SELECT * FROM product_spec WHERE product_id = " . clean_input($productid) ;
$result1 = query($sql1);
$row1 = fetch_array($result1);
/* html markup follows */

पुनर्रचना:

चूंकि मैं कोड के इस विशिष्ट भाग में चीजों को बदलने के लिए कुछ काम कर रहा हूं, इसलिए मैंने इसे रिपॉजिटरी पैटर्न का उपयोग करने के लिए बदल दिया और इसे ऑब्जेक्ट-ओरिएंटेड MySQL सुविधाओं का उपयोग करने के लिए अपग्रेड किया:

//some implementation details omitted 
$this->repository = new SpecRepository($mysql);
if ($verid)
    $row1 = $this->repository->getSpecByVersion($verid);
else 
    $row1 = $this->repository->getSpecByProductId($productid);
/* html markup follows to be refactored or left alone till another time*/

//added new class:
class SpecRepository extends MySqlRepository
{

    function getSpecByVersion(int $verid)
    {
        return $this->getMySql()->paramQuery("
            SELECT * FROM product_spec WHERE id = ?
        ", $verid)->getSingleArray();
    }

    function getSpecByProductId(int $productid)
    {
        return $this->getMySql()->paramQuery("
            SELECT * FROM product_spec WHERE product_id = ?
        ", $productid)->getSingleArray();
    }
}

क्या मुझे ऐसा करना चाहिए?

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

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

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

मैंने पहली बार रिफ्लेक्टर क्यों लगाया?

मेरे मामले में मैं एक नई उत्पाद लाइन के लिए नई कार्यक्षमता जोड़ रहा हूं, इसलिए मुझे या तो समान उत्पाद लाइनों के लिए मौजूदा कोड संरचना का पालन करना होगा, या अपना खुद का लिखना होगा।


ओटी लेकिन विचार करने के लिए कुछ ऐसा है जिसे Select * from ..एक विरोधी पैटर्न माना जा सकता है। देखें stackoverflow.com/q/3639861/31326
पीटर एम

1
@PeterM: जब तक आप एक ORM नहीं लिख रहे हैं, उस स्थिति में select *यह "सर्वोत्तम अभ्यास" बन जाता है।
रॉबर्ट हार्वे

@RobertHarvey किस मामले में मैं सवाल कर रहा हूं कि आप अपना स्वयं का ORM क्यों लिख रहे हैं: D
पीटर M

मैंने अधिक अप्रासंगिक कारणों के लिए रिफ्लेक्टर किए हैं। जैसे ही लाभ कम हो, तकनीकी ऋण में कटौती करना अच्छा है। ऐसा लगता है कि यह आपका मामला है। सवाल यह है कि क्या आपके पास यह सुनिश्चित करने के लिए सही परीक्षण हैं कि कोड अभी भी उम्मीद के मुताबिक काम करता है?
Laiv

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

जवाबों:


13

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

मैं यह भी कहूंगा कि आपके द्वारा प्राप्त किया गया लाभ कोड था जिसे समझना आसान है, कम से कम मेरे दृष्टिकोण से, कोई ऐसा व्यक्ति जो अपने कोड आधार को नहीं जानता है।


सामान्य रूप में:

क्या रिफ्लेक्टरिंग अन्य डेवलपर्स के लिए आपके कोड को समझना आसान बनाता है?

क्या रीफैक्टरिंग से कोड बढ़ाने में आसानी होती है?

क्या रीफैक्टरिंग से कोड को बनाए रखना आसान हो जाता है?

क्या रिफैक्टिंग से डिबग करना आसान हो जाता है?

यदि इनमें से किसी का उत्तर "हाँ" था, तो यह इसके लायक था, और यह "चारों ओर चलने वाले कोड" से अधिक था?

यदि इन सभी का उत्तर "नहीं" था, तो शायद इसे वापस लेने की आवश्यकता नहीं थी।

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


9

यदि आप एक मोनोलिथ को अलग कर रहे हैं, तो रिफ्लेक्टिंग ब्लोट करता है।

हालाँकि, आपको पहले ही लाभ मिल गया।

"मेरे मामले में मैं एक नई उत्पाद लाइन के लिए नई कार्यक्षमता जोड़ रहा हूं।"

आप चीजों को तोड़े बिना आसानी से एक मोनोलिथ में कार्यक्षमता नहीं जोड़ सकते।

आपने कहा कि समान कोड डेटा प्राप्त कर रहा है और मार्कअप कर रहा है। महान, जब तक आप बदलना नहीं चाहते हैं कि आप किन कॉलमों का चयन कर रहे हैं और कुछ स्थितियों में दिखाने के लिए हेरफेर कर रहे हैं। अचानक, आपका मार्कअप कोड एक निश्चित मामले में काम करना बंद कर देता है और आपको रिफ्लेक्टर करना पड़ता है


हां, लेकिन मैं नई कार्यक्षमता के लिए भी मोनोलिथ को जोड़कर रख सकता हूं :) यानी मैं एक नया if/elseब्लॉक जोड़ूंगा और एसक्यूएल स्टेटमेंट को जोड़ने के लिए कोड की मूल शैली का पालन करूंगा, और फिर मैं उसी मोनोलिथ फाइल में नया HTML मार्कअप डालूंगा। और स्तंभों को बदलने के लिए मुझे आवास SQL ​​लाइनों के लिए जिम्मेदार / अन्यथा ब्लॉक मिलेगा, और उस फ़ाइल को तोड़ने के बिना कॉलम में परिवर्तन करने के लिए उस एसक्यूएल को संपादित करें।
डेनिस

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

2

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

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

मैं निम्नलिखित कारणों से रिफ्लैक्टरिंग को महत्व देता हूं:

  • मैं कोड को बेहतर समझता हूं
  • मैं डुप्लिकेट कोड को हटा देता हूं, अगर मेरे पास एक बग है तो मुझे हर उस जगह शिकार नहीं करना है जहां कोड कॉपी पेस्ट किए गए थे
  • मैं ऐसी कक्षाएं बनाता हूं जिनकी अपनी अच्छी तरह से परिभाषित भूमिका होती है। उदाहरण के लिए, मैं एक HTML पृष्ठ, एक XML फ़ीड या एक पृष्ठभूमि नौकरी को हाइड करने के लिए उसी रिपॉजिटरी का पुन: उपयोग कर सकता हूं। यह संभव नहीं होता अगर डेटाबेस एक्सेस कोड केवल HTML वर्ग में रहता
  • यदि वे वर्तमान वास्तविकता के साथ मेल नहीं खाते हैं, तो मैं चर, विधियों, वर्गों, मॉड्यूल, फ़ोल्डरों का नाम बदल देता हूं; मैं commentचर नामों के माध्यम से कोड, विधि के नाम
  • मैं यूनिट परीक्षण और रीफैक्टरिंग के बीच संयोजन के साथ जटिल कीड़े को हल करता हूं
  • मेरे पास पूरे मॉड्यूल, पैकेजों को बदलने के लिए लचीलापन है। यदि वर्तमान ORM पुराना है, छोटी गाड़ी है या संयुक्त राष्ट्र का रखरखाव है, तो इसे बदलना आसान है यदि यह पूरे प्रोजेक्ट में नहीं फैला है।
  • मैं नई क्षमताओं या सुधारों की खोज करता हूं जिसके परिणामस्वरूप ग्राहक के लिए प्रस्ताव आते हैं।
  • मैंने पुन: प्रयोज्य घटकों का निर्माण किया। यह सबसे बड़ा लाभ में से एक था क्योंकि उस परियोजना में किए गए कार्य को किसी अन्य क्लाइंट / प्रोजेक्ट के लिए फिर से उपयोग किया जा सकता था।
  • मैं अक्सर डंबेस्ट, हार्डकोड, निराला समाधान के साथ शुरू करता हूं और एक बार और सीखने के बाद मैं इसे रिफ्लेक्टर करता हूं। यह बाद का क्षण आज या शायद कई दिनों के बाद हो सकता है। मैं architectसमाधान के लिए बहुत अधिक समय खर्च नहीं करना चाहता । यह लिखते समय आएगा - कोड को आगे और पीछे फिर से लिखना।

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

मैंने बग भी पेश किए। मैं देख सकता हूं कि कुछ क्यूए क्यों पूछ रहे हैं are you guys doing refactoring? because everything stopped working!यह टीम को गले लगाने का जोखिम है और हमें हमेशा इसके बारे में पारदर्शी रहना होगा।

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


यह एक डाउन वोट के बहुत करीब है - 'कंप्यूटर प्रोग्रामर' में कोई 'मैं' नहीं है। 'I' से आप मुझे 'I' करते हैं (वोट के लिए) या क्या आपका मतलब है कि अभी और भविष्य में कोड पर काम करने वाले डेवलपर्स?
मटनज़

मैंने उस पर भी ध्यान दिया, लेकिन मैंने इसे शब्दों में बदल दिया। इसके अलावा मैंने कई वर्षों तक एकल डेवलपर के रूप में काम किया और जब मैंने यह उत्तर लिखा तो मैंने उस अनुभव से दोहराया। मैं हालांकि के Iसाथ बदल सकता है to
एड्रियन इफोड

1

मुझे लगता है कि आपको खुद से जो सवाल पूछना है, वह इतना अधिक नहीं है "क्या कोई लाभ है?" लेकिन "इस काम के लिए कौन भुगतान करेगा?"

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

यह सब बहुत आसान है जब आप कोड देखने के लिए एक देव टीम पर होते हैं और इसे 'बेहतर' बनाने के लिए इसे रिफलेक्टर करना चाहते हैं। लेकिन 'बेहतर कोड' पर एक मूल्य डालना जब उत्पाद पहले से ही काम करता है तो वास्तव में कठिन है।

'नई सुविधाओं के तेजी से विकास ’जैसी चीजें इसे काटती नहीं हैं क्योंकि वे कम लागत वाले हैं। आपको बिक्री उत्पन्न करने की आवश्यकता है।


1

मेरी राय में रिफैक्टिंग एक अच्छा निवेश है।

अन्यथा आपको जल्द ही तकनीकी ऋण (अनसुलझी समस्याएं, बुरा कोड जो केवल कुछ शर्तों के तहत काम कर रहा है, आदि) मिलेगा। तकनीकी ऋण जल्द ही बड़े और बड़े हो जाएंगे, जब तक कि सॉफ्टवेयर अब बनाए रखने योग्य नहीं है।

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

यदि आपको अपने बॉस या सहकर्मियों को समझाना है, तो आपको चुस्त तरीकों (जैसे SCRUM) के बारे में कुछ किताबें पढ़नी चाहिए और संचालित विकास का परीक्षण करना चाहिए।

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