क्या उन्हें क्लास या फ़ंक्शन में लपेटने के बजाय लंबे लेकिन सीधे कोड को कॉपी और पेस्ट करना स्वीकार्य है?


29

मान लीजिए कि मेरे पास इंटरनेट से जुड़ने और इसके जैसे कनेक्शन परिणाम दिखाने के लिए कोड का एक खंड है:

HttpRequest* httpRequest=new HttpRequest();
httpRequest->setUrl("(some domain .com)");
httpRequest->setRequestType(HttpRequest::Type::POST);
httpRequest->setRequestData("(something like name=?&age=30&...)");
httpRequest->setResponseCallback([=](HttpClient* client, HttpResponse* response){
    string responseString=response->getResponseDataString();
        if(response->getErrorCode()!=200){
            if(response->getErrorCode()==404){
                Alert* alert=new Alert();
                alert->setFontSize(30);
                alert->setFontColor(255,255,255);
                alert->setPosition(Screen.MIDDLE);
                alert->show("Connection Error","Not Found");
            }else if((some other different cases)){
                (some other alert)
            }else
                Alert* alert=new Alert();
                alert->setFontSize(30);
                alert->setPosition(Screen.MIDDLE);
                alert->setFontColor(255,255,255);
                alert->show("Connection Error","unknown error");
            }
        }else{
            (other handle methods depend on different URL)
        }
}

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

मेरा प्रश्न यह है कि क्या कोड की निर्भरता को कम करने के लिए उन्हें किसी फ़ंक्शन में लपेटने के बजाय लंबे लेकिन सीधे कोड को कॉपी और पेस्ट करना स्वीकार्य है?


89
कल्पना कीजिए कि आपके पास उस कोड में एक बग है, जैसे कि आपके द्वारा आवंटित वस्तुओं को मुक्त नहीं करना। (क्या आपका ढांचा Alertवस्तुओं को मुक्त करता है?) अब कल्पना करें कि बग को ठीक करने के लिए आपको इस कोड की प्रत्येक प्रतिलिपि की गई आवृत्ति को ढूंढना होगा। अब कल्पना करें कि यह आप नहीं हैं जो इसे करना है, बल्कि एक पागल कुल्हाड़ी हत्यारा है जो आपको जानता है कि ये सभी प्रतियां पहले स्थान पर थीं।
सेबेस्टियन रेडल

8
और BTW, एक जगह में नेटवर्किंग और एरर डिस्प्ले को मिक्स करना पहले से ही एक बड़ा नो-नो, IMHO है।
स्लेस्के

11
नहीं कभी नहीं। पूरी तरह से अस्वीकार्य। यदि आप मेरी परियोजना पर थे, तो आप अब मेरी परियोजना पर नहीं होंगे और आप एक प्रशिक्षण कार्यक्रम या पीआईपी पर होंगे।
नृगिफ़

10
और इसके साथ ही पर्यवेक्षक का कहना है कि "मेरी स्क्रीन के बीच में यह अलर्ट बॉक्स एक पूर्ण आतंक है। मैं कैट जिफ़ देख रहा हूं और पॉप-अप हर बार जब भी यह दिखाई देता है, तो मेरा विचार अवरुद्ध कर रहा है। कृपया इसे ऊपरी-दाईं ओर ले जाएं। । " 3 सप्ताह बाद "बिल्ली ने क्या किया? मैं अब अपनी बिल्ली की जफों को बंद नहीं कर सकता क्योंकि आपका पॉप-अप एक्स को ऊपरी-दाएँ में कवर कर रहा है, इसे ठीक करें।"
मंकीजियस

11
मुझे लगता है कि यहां सभी को लगता है कि यह एक बुरा विचार है। लेकिन सवाल को घुमा देने के लिए, आप इस कोड को एक अलग वर्ग या फ़ंक्शन में क्यों नहीं डालेंगे?
कार्ल जार्जेटेन

जवाबों:


87

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

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

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

Https://softwareengineering.stackexchange.com/a/103235/63172 भी देखें


19
... और कौन जानता है कि ये 30 लाइनें वास्तव में उन अन्य लोगों की तरह ही हैं जिन्हें आपने पहले देखा था या यदि किसी कारण से उसकी कॉपी में किसी अन्य पोर्ट या आईपी पते पर स्विच किया गया था। निहित धारणा है कि " किसी भी 30 लाइनों में से किसी एक का गुच्छा HttpRequestसभी के साथ शुरू होता है ", सुस्ती बनाना आसान है।
नल

@null उत्कृष्ट बिंदु। मैंने एक बार कोड पर काम किया था जहाँ डेटाबेस कनेक्शन हुकअप कॉपी किए गए थे और सभी पर चिपकाए गए थे, लेकिन सेटअप में कुछ सूक्ष्म अंतर थे। मुझे नहीं पता था कि ये महत्वपूर्ण थे, जानबूझकर परिवर्तन, या सिर्फ यादृच्छिक अंतर
user949300

54

नहीं।

वास्तव में, यहां तक ​​कि आपके "सरल" कोड को छोटे भागों में विभाजित किया जाना चाहिए। कम से कम दो।

एक कनेक्शन बनाने और सामान्य 200 प्रतिक्रिया को संभालने के लिए। उदाहरण के लिए, यदि आप कुछ मामलों में POST से PUT में बदल जाते हैं तो क्या होगा? क्या होगा यदि आप इन कनेक्शनों के बिल बना रहे हैं और आपको कुछ मल्टी-थ्रेडिंग या कनेक्शन-पूलिंग की आवश्यकता है? विधि के लिए एक तर्क के साथ एक ही स्थान पर कोड होने से यह बहुत आसान हो जाएगा

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



आप SRP को भी उद्धृत कर सकते हैं: एक कोड ब्लॉक होना जिसका केवल एक ही उद्देश्य है, इसे समझना और बनाए रखना इतना आसान हो जाता है ..
रोलाण्ड तेप्प

यह एक मामला है जहां DRY और SRP वास्तव में संरेखित हैं। कभी-कभी वे नहीं करते।
user949300

18

क्या यह कॉपी और पेस्ट करने के लिए स्वीकार्य है ...

नहीं।

मेरे लिए, निर्णायक तर्क यह है:

... यह आमतौर पर इस्तेमाल किया जाता है ...

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

यह सीधा है और जटिल नहीं है ...

और इसलिए किसी फ़ंक्शन में रिफ्लेक्टर करने के लिए सभी आसान होना चाहिए।

... वहाँ यूआरएल, फ़ॉन्ट आकार जैसी सेटिंग्स के बंडल हैं ...

और उपयोगकर्ताओं को क्या पसंद है बदलना करते हैं? फ़ॉन्ट, फ़ॉन्ट आकार, रंग, आदि।

अभी व; कितने स्थानों पर आपको उन सभी समान रंग / फ़ॉन्ट / आकार को फिर से प्राप्त करने के लिए उस समान कोड को बदलना होगा? (अनुशंसित उत्तर: सिर्फ एक )।

... कोड सेगमेंट में वर्ग के बीच थोड़ा बदलाव होता है (उदाहरण: url, अनुरोध डेटा, त्रुटि कोड हैंडल मामले, सामान्य हैंडल मामले ...)

भिन्नता => फ़ंक्शन पैरामीटर (एस)।


"और उपयोगकर्ता क्या बदलना पसंद करते हैं? फ़ॉन्ट्स, फ़ॉन्ट आकार, रंग, आदि" यह इतना सौदा है। क्या आप वास्तव में दर्जनों स्थानों पर इसे बदलना चाहते हैं?
डैन

8

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

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

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


6

कुछ परिस्थितियों में नकल ठीक है। लेकिन इस एक में नहीं। वह तरीका बहुत जटिल है। एक निचली सीमा है, जब दोहराव "फैक्टरिंग आउट" एक विधि से आसान है।

उदाहरण के लिए:

def add(a, b)
    return a + b
end

मूर्ख है, बस a + b करते हैं।

लेकिन जब आप बस थोड़ा सा, थोड़ा और अधिक जटिल हो जाते हैं, तो आप आमतौर पर लाइन पर पहुंच जाते हैं।

foo.a + foo.b

बन जाना चाहिए

foo.total
def foo
    ...
    def total
        return self.a + self.b
    end
end

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

अंत में, एक वेब अनुरोध करने के लिए मैं एक कॉल करना चाहूंगा जैसे कि:

Web.Post(URI, Params, ResponseHandler);

वह लाइन वह है जो मेरे कोड में होगी। फिर जब मुझे "कैसे सामान मिलता है" में बदलाव करने की आवश्यकता थी, तो मैं बहुत कम प्रयास के साथ जल्दी से ऐसा कर सकता था।

यह कोड DRY भी रखता है और SRP के साथ मदद करता है ।


0

किसी भी आकार / जटिलता की परियोजना में, मैं निम्नलिखित उद्देश्यों के लिए आवश्यकता पड़ने पर कोड ढूंढने में सक्षम होना चाहता हूं:

  1. इसे तोड़ने पर ठीक करें
  2. कार्यक्षमता को बदलें
  3. इसका पुनः उपयोग करें।

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

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


0

एक वर्ग और / या एक समारोह बेहतर है, कम से कम मेरी राय में। एक बार के लिए, यह फ़ाइल को छोटा बनाता है जो बहुत भारी लाभ होता है यदि आप वेब एप्लिकेशन या छोटे स्टोरेज वाले उपकरणों के लिए एप्लिकेशन (IoT, पुराने फोन आदि) से निपटते हैं।

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

मैंने एक पूरा SQL दुभाषिया लिखा है, ताकि मैं PHP में MySQL से MySQLi में बेहतर स्विच कर सकूं , क्योंकि मुझे बस अपने दुभाषिया को बदलना है और हर काम करना है, हालांकि यह एक चरम उदाहरण का एक सा है।


-1

यह तय करने के लिए कि एक कोड को दो बार कहा जाना चाहिए या एक फ़ंक्शन में ले जाना चाहिए या नहीं, यह निर्धारित करने का प्रयास करें कि कौन अधिक संभावित है:

  1. कोड के दोनों उपयोगों को एक ही तरीके से बदलना आवश्यक होगा।

  2. कोड के कम से कम एक उपयोग को बदलना आवश्यक होगा ताकि वे अलग-अलग हों।

पहले मामले में, यह संभव होगा कि एक फ़ंक्शन को दोनों usages को संभालना बेहतर होगा; बाद के मामले में, दो चरणों के लिए अलग-अलग कोड होना बेहतर होगा।

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

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