भ्रम कोड दोहराव


56

सामान्य वृत्ति किसी भी कोड के दोहराव को हटाने के लिए है जिसे आप कोड में देखते हैं। हालांकि, मैंने खुद को ऐसी स्थिति में पाया, जहां नकल भ्रम की स्थिति है ।

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

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

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

समस्याएं हैं:

  • अंतर इतने मिनट हैं कि कोड सभी दृश्यों में लगभग समान दिखता है ,
  • देखते हैं तो कई जब आप कोड के लिए, विवरण देखते हैं कि मतभेद है एक सा एक जैसे नहीं

मुझे इस स्थिति को कैसे संभालना चाहिए?
क्या पूरी तरह से कॉलबैक कॉल से बना कोर लॉजिक एक अच्छा समाधान है?
या मुझे कोड को डुप्लिकेट करना चाहिए और कॉलबैक-आधारित कोड की जटिलता को छोड़ना चाहिए?


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

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

याद रखें, आप केवल उसी कोड का पुन: उपयोग कर सकते हैं जो समान कार्य करता है। यदि आपका ऐप अलग-अलग स्क्रीन पर अलग-अलग काम करता है, तो उसे अलग-अलग कॉलबैक की आवश्यकता होगी। इसके बारे में कोई अगर, और, या मगर नहीं।
corsiKa

13
इस पर अंगूठे का मेरा व्यक्तिगत नियम है: यदि मैं एक स्थान पर कोड में बदलाव करता हूं, तो क्या यह एक बग है, अगर मैं हर जगह एक समान परिवर्तन नहीं करता हूं? यदि हां, तो यह नकल का सबसे खराब प्रकार है। अगर मुझे यकीन नहीं है, तो अभी के लिए जो भी अधिक पढ़ने योग्य है, साथ चलें। आपके उदाहरण में व्यवहार में अंतर जानबूझकर है, और बग नहीं माना जाता है, इस प्रकार कुछ दोहराव ठीक है।
Ixrec

आपको एस्पैक्ट ओरिएंटेड प्रोग्रामिंग के बारे में पढ़ने में रुचि हो सकती है।
बेन जैक्सन

जवाबों:


53

अंततः आपको इस बारे में निर्णय लेना है कि क्या डुप्लिकेट को खत्म करने के लिए समान कोड को संयोजित किया जाए।

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

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

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

डिजाइन के लिए अपर्याप्त ध्यान एक ख़तरा है, लेकिन अति-डिज़ाइन से भी सावधान रहें।


"दुर्भाग्यपूर्ण प्रवृत्ति" के बारे में आपकी टिप्पणी और दिशा-निर्देशों का आँख बंद करके पालन करना मुझे लगता है।
मैएल

1
@Mael क्या आप कह रहे हैं कि यदि आप भविष्य में इस कोड को बनाए नहीं रखेंगे, तो आपके पास सही डिज़ाइन पाने के लिए अच्छे कारण नहीं होंगे? (कोई अपराध नहीं, बस आप जानना चाहते हैं कि आप उसके बारे में क्या सोचते हैं)
स्पॉट

2
@ बेशक हम इसे केवल वाक्यांश का दुर्भाग्यपूर्ण मोड़ मान सकते हैं! : D हालांकि, मुझे लगता है कि हमें खुद के साथ उतना ही सख्त होना चाहिए जितना हम दूसरों के लिए हैं जब कोड लिखता हूं (मैं खुद को एक दूसरे के रूप में मानता हूं जब मैं अपना कोड लिखने के 2 सप्ताह बाद पढ़ता हूं)।
स्पॉट

2
@ user61852 तो आप कोडलेस कोड को बहुत नापसंद करेंगे ।
रबडकॉक

1
@ user61852, haha - लेकिन अगर यह क्या करता है सब निर्भर (सूचना के आधार पर प्रश्न में दिए गए नहीं)? कुछ चीजें अतिरिक्त निश्चितता से कम सहायक होती हैं।

43

याद रखें कि DRY ज्ञान के बारे में है । इससे कोई फर्क नहीं पड़ता कि कोड के दो टुकड़े समान, समान, या पूरी तरह से अलग हैं, क्या मायने रखता है यदि आपके सिस्टम के बारे में ज्ञान का एक ही टुकड़ा उन दोनों में पाया जा सकता है।

ज्ञान का एक टुकड़ा एक तथ्य हो सकता है ("इच्छित मूल्य से अधिकतम अनुमत विचलन 0.1% है") या यह आपकी प्रक्रिया का कुछ पहलू हो सकता है ("इस कतार में कभी भी तीन से अधिक आइटम नहीं होते हैं")। यह अनिवार्य रूप से आपके स्रोत कोड में एन्कोड की गई जानकारी का कोई एक टुकड़ा है।

इसलिए जब आप यह तय कर रहे हैं कि क्या कुछ दोहराव है जिसे हटा दिया जाना चाहिए, तो पूछें कि क्या यह ज्ञान का दोहराव है। यदि नहीं, तो यह संभवतः आकस्मिक दोहराव है, और इसे कुछ सामान्य स्थान पर निकालने से समस्याएँ पैदा होंगी जब आप बाद में एक समान घटक बनाना चाहते हैं, जहाँ वह स्पष्ट रूप से डुप्लिकेट किया गया भाग अलग है।


12
इस! DRY का फोकस डुप्लीकेट बदलावों से बचा रहा है ।
मैथ्यू एम।

यह काफी मददगार है।

1
मैंने सोचा था कि सूखी का ध्यान केंद्रित सुनिश्चित करना है कि कोड का कोई दो बिट्स देखते हैं कि था चाहिए समान व्यवहार करते हैं लेकिन नहीं है। यह समस्या दोहरा काम नहीं है क्योंकि कोड परिवर्तन को दो बार लागू किया जाना है, वास्तविक समस्या यह है कि कोड परिवर्तन को दो बार लागू किया जाना चाहिए, लेकिन नहीं।
gnasher729

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

1
इसके अलावा आवश्यक दोहराव और आकस्मिक दोहराव , रूबी में एक आकस्मिक डॉपेलगेंगर और मैं DRY-ed Up My Code और अब इट्स हार्ड टू वर्क के साथ देखें। क्या हुआ? । आकस्मिक डुप्लिकेट एक संदर्भ सीमा के दोनों किनारों पर भी होते हैं । सारांश: केवल डुप्लिकेट को मर्ज करें यदि यह अपने ग्राहकों के लिए इन निर्भरताओं को एक साथ संशोधित करने के लिए समझ में आता है ।
एरिक

27

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


5
नहीं, मैंने इस पर विचार नहीं किया है। सुझाव के लिए धन्यवाद। रणनीति पैटर्न के बारे में एक त्वरित पढ़ने से ऐसा लगता है कि मैं कुछ ढूंढ रहा हूं। मैं निश्चित रूप से आगे की जांच करूंगा।
मैएल

3
वहाँ टेम्पलेट विधि पैटर्न । आप इस पर भी विचार कर सकते हैं
शकील

5

बदलाव की क्षमता क्या है? उदाहरण के लिए, हमारे आवेदन में प्रत्येक क्षेत्र के लिए 4 या अधिक उपयोगकर्ता प्रकारों की क्षमता वाले 8 अलग-अलग व्यावसायिक क्षेत्र हैं। उपयोगकर्ता प्रकार और क्षेत्र के आधार पर दृश्य अनुकूलित किए जाते हैं।

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

जैसा कि @ dan1111 ने उल्लेख किया है, यह एक निर्णय कॉल के लिए नीचे आ सकता है। समय में, आप पा सकते हैं कि यह काम करता है या नहीं।


2

एक मुद्दा यह हो सकता है कि आप कार्यक्षमता के केवल एक स्तर तक एक इंटरफ़ेस (सैद्धांतिक इंटरफ़ेस, भाषा सुविधा नहीं) प्रदान कर रहे हैं:

A(a,b,c) //a,b,c are your callbacks or other dependencies

कई स्तरों के बजाय इस बात पर निर्भर करता है कि कितना नियंत्रण आवश्यक है:

//high level
A(a,b,c)
//lower
A myA(a,b)
B(myA,c)
//even lower
A myA(a)
B myB(myA,b)
C myC(myB,c)
//all the way down to you just having to write the code yourself

जहां तक ​​मैंने समझा, आप केवल कार्यान्वयन विवरण (वहां की अन्य चीजें) छिपाते हुए उच्च स्तरीय इंटरफ़ेस (ए) को उजागर करते हैं।

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

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

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

किसी एक वस्तु का उपयोग करें जहाँ आपको थोड़ा नियंत्रण चाहिए।

सबसे कम स्तर की कार्यक्षमता का उपयोग करें जब कुछ अजीबता होने की आवश्यकता होती है।

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


1

पहले से ही अन्य उपयोगी उत्तर हैं। मैं जोड़ दूंगा।

दोहराव बुरा है क्योंकि

  1. यह कोड को बंद कर देता है
  2. यह कोड के हमारे संकलन को बंद कर देता है लेकिन सबसे महत्वपूर्ण बात
  3. क्योंकि अगर आप यहाँ कुछ बदलते हैं और आपको वहाँ कुछ बदलना भी है , तो आप भूल सकते हैं / बग्स को शुरू कर सकते हैं / .... और इसे कभी नहीं भूलना मुश्किल है।

तो मुद्दा यह है: आप इसके लिए नकल को खत्म नहीं कर रहे हैं या क्योंकि किसी ने कहा कि यह महत्वपूर्ण है। आप ऐसा कर रहे हैं क्योंकि आप बग्स / समस्याओं को कम करना चाहते हैं। आपके मामले में, ऐसा प्रतीत होता है कि यदि आप किसी दृश्य में कुछ बदलते हैं, तो संभवतः आपको अन्य सभी दृश्यों में ठीक उसी पंक्ति को बदलने की आवश्यकता नहीं होगी । तो आपके पास स्पष्ट दोहराव है , न कि वास्तविक दोहराव।

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

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