मैं कैस्केडिंग रिफैक्टरिंग से कैसे बचूँ?


52

मुझे एक प्रोजेक्ट मिला है। इस परियोजना में मैंने इसे एक फीचर जोड़ने के लिए रीफ़ैक्टर करने की इच्छा की, और मैंने फ़ीचर को जोड़ने के लिए प्रोजेक्ट को फिर से सक्रिय कर दिया।

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

मैं भविष्य में इस तरह के कैस्केडिंग रिफैक्टरिंग से कैसे बच सकता हूं? क्या यह सिर्फ मेरी पिछली कक्षाओं का एक लक्षण है जो एक दूसरे पर बहुत कसकर निर्भर करता है?

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

बड़ा संपादन जो मैंने पांच दिन पहले वादा किया था:

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

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

for(auto&& a : as) {
     f(a);
}

हालाँकि, इस संदर्भ को प्राप्त करने के लिए, मुझे इसे कुछ और चीजों में बदलने की आवश्यकता थी

std::vector<Context> contexts;
for(auto&& a : as)
    contexts.push_back(g(a));
do_thing_now_we_have_contexts();
for(auto&& con : contexts)
    f(con);

इसका मतलब यह है कि सभी ऑपरेशनों के लिए जो एक हिस्सा हुआ करते थे f, उनमें से कुछ को gबिना किसी संदर्भ के संचालित होने वाले नए फ़ंक्शन का एक हिस्सा बनाने की आवश्यकता होती है, और उनमें से कुछ को अब आस्थगित के एक हिस्से से बनाने की आवश्यकता होती है f। लेकिन सभी तरीकों को fइस संदर्भ की आवश्यकता नहीं है या नहीं चाहिए- उनमें से कुछ को एक अलग संदर्भ की आवश्यकता है जो वे अलग-अलग साधनों के माध्यम से प्राप्त करते हैं। तो हर उस चीज के लिए fजो कॉलिंग को समाप्त करती है (जो कि मोटे तौर पर, बहुत ज्यादा सब कुछ बोलती है ), मुझे यह निर्धारित करना था कि क्या, यदि कोई हो, संदर्भ की जरूरत है, तो वे इसे कहां से प्राप्त करें, और उन्हें पुराने fसे नए fऔर नए में कैसे विभाजित करें g

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


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

5
@ जूल्स: कड़ाई से बोलते हुए, सुविधा अन्य डेवलपर्स को एक विशेष प्रकार के विस्तार को जोड़ने की अनुमति देने के लिए थी, इसलिए यह सुविधा रिफ्लेक्टर थी, जिसने वर्ग संरचना को अधिक खुला बना दिया था।
डेडएमजी

5
मैंने सोचा कि यह हर पुस्तक और लेख में चर्चा की जाती है जो कि रिफैक्टिंग के बारे में बात करती है? स्रोत नियंत्रण बचाव के लिए आता है; यदि आपको लगता है कि चरण A को करने के लिए आपको चरण B को पहले करना है, तो A को स्क्रैप करें और B को पहले करें।
रवांग

4
@DeadMG: यह वह पुस्तक है जिसे मैं मूल रूप से अपनी पहली टिप्पणी में उद्धृत करना चाहता था: "गेम" पिक-अप स्टिक्स "मिकाडो विधि के लिए एक अच्छा रूपक है। आप" तकनीकी ऋण "को समाप्त करते हैं-लगभग हर सॉफ्टवेयर में अंतर्निहित विरासत की समस्याएं। सिस्टम- आसान-से-लागू नियमों के एक सेट का पालन करके। जब तक आप केंद्रीय मुद्दे को उजागर नहीं करते, परियोजना को ढहने के बिना आप प्रत्येक अंतर्निर्धारित निर्भरता को सावधानीपूर्वक निकालते हैं। "
रवांग

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

जवाबों:


69

पिछली बार मैंने अप्रत्याशित परिणामों के साथ एक रिफैक्टरिंग शुरू करने की कोशिश की थी, और मैं एक दिन के बाद बिल्ड और / या परीक्षणों को स्थिर नहीं कर सका , मैंने त्याग दिया और रिफैक्टरिंग से पहले पॉइंट पर कोडबेस को वापस कर दिया।

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

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

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


53

क्या यह सिर्फ मेरी पिछली कक्षाओं का एक लक्षण है जो एक दूसरे पर बहुत कसकर निर्भर करता है?

ज़रूर। अन्य परिवर्तनों के असंख्य होने का एक कारण कपलिंग की परिभाषा बहुत अधिक है।

मैं कैस्केडिंग रिफैक्टरों से कैसे बचूँ?

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

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


33
+1 अधिक बुरी तरह से रिफैक्टरिंग की आवश्यकता होती है, जितना अधिक व्यापक रूप से रीफैक्टरिंग पहुंचेगा। यह बात की प्रकृति है।
पॉल ड्रेपर

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

+1 एडेप्टर ठीक उसी तरह है जिस तरह से आप पहले कोड को बदलना चाहते हैं।
विंकब्रेस

17

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

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


4
मैं नहीं देखता कि ऐसी स्थिति कैसे पैदा हो सकती है। किसी विधि के इंटरफेस के किसी भी उचित रीफैक्टरिंग के लिए मापदंडों का एक आसानी से निर्धारित नया सेट होना चाहिए जिसे पारित किया जा सकता है जिसके परिणामस्वरूप कॉल का व्यवहार वैसा ही होगा जैसा कि परिवर्तन से पहले था।
जूल्स

3
मैं कभी भी ऐसी स्थिति में नहीं था, जहाँ मैं इस तरह की रिफैक्टिंग करना चाहता था, लेकिन मुझे यह कहना होगा कि यह मेरे लिए काफी असामान्य है। क्या आप कह रहे हैं कि आपने इंटरफ़ेस से कार्यक्षमता को हटा दिया है? यदि हां, तो यह कहां गया? एक और इंटरफ़ेस में? या कहीं और?
जूल्स

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

11
@ डीडीएमजी: यह अजीब लगता है: आप एक ऐसी सुविधा को हटा रहे हैं जिसकी आपको कोई आवश्यकता नहीं है, जैसा कि आप कहते हैं। लेकिन दूसरी ओर, आप लिखते हैं "परियोजना पूरी तरह से गैर-कार्यात्मक हो जाती है" - जो वास्तव में लगता है कि फीचर की बिल्कुल आवश्यकता है। कृपया स्पष्ट करें।
डॉक्टर ब्राउन

26
@DeadMG ऐसे मामलों में आप सामान्य रूप से नई सुविधा विकसित करेंगे, यह सुनिश्चित करने के लिए परीक्षण जोड़ें, नए इंटरफ़ेस का उपयोग करने के लिए मौजूदा कोड को परिवर्तित करें, और फिर (अब) शानदार पुरानी सुविधा को हटा दें। इस तरह, वहाँ एक बिंदु नहीं होना चाहिए जिस पर चीजें टूटती हैं।
सपि

12

मैं भविष्य में इस तरह के कैस्केडिंग रिफैक्टर से कैसे बच सकता हूं?

इच्छाधारी सोच डिजाइन

लक्ष्य उत्कृष्ट ओओ डिजाइन और नई सुविधा के लिए कार्यान्वयन है। रिफैक्टिंग से बचना भी एक लक्ष्य है।

खरोंच से शुरू करें और नई सुविधा के लिए एक डिज़ाइन बनाएं जो आप चाहते हैं वह आपके पास है। इसे अच्छी तरह से करने के लिए समय निकालें।

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

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

सांख्यिकी, सबक आदि सीखे।

एक मौजूदा विधि कॉल में डिफ़ॉल्ट पैरामीटर को जोड़ने के रूप में रिफैक्टरिंग सरल है; या एक स्थिर वर्ग विधि के लिए एक कॉल।

मौजूदा कक्षाओं के विस्तार के तरीके नए डिजाइन की गुणवत्ता को पूर्ण न्यूनतम जोखिम के साथ रखने में मदद कर सकते हैं।

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

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

मौजूदा कोड से इस नई कार्यक्षमता के किसी भी अवशेष को शुद्ध करें। यहाँ, पूर्ण और अच्छी तरह से समझाया गया नया फीचर कार्यक्षमता, रिफैक्टरिंग से बचने से अधिक महत्वपूर्ण है।


9

से (अद्भुत) पुस्तक माइकल पंख से विरासत कोड के साथ प्रभावी ढंग से काम कर रहे :

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

यदि बाद में आप उस बिंदु के चारों ओर कोड को कवर कर सकते हैं जहां आपने निर्भरता को तोड़ा है, तो आप उस निशान को भी ठीक कर सकते हैं।


6

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

समाधान के लिए "ऐसा नहीं करना है, तो" है । वास्तविक परियोजनाओं में यही होता है। परिणामस्वरूप, बहुत से पुराने APIs में बदसूरत इंटरफेस या परित्यक्त (हमेशा शून्य) पैरामीटर होते हैं, या DoThisThing2 () नाम के फ़ंक्शन होते हैं, जो पूरी तरह से अलग पैरामीटर सूची के साथ DoThisThing () के समान होता है। अन्य सामान्य ट्रिक्स में ग्लोबल्स या टैग किए गए पॉइंटर्स में सूचनाओं को शामिल करना शामिल है ताकि फ्रेमवर्क के एक बड़े हिस्से को स्मगल करने के लिए इसे स्मगल किया जा सके। (उदाहरण के लिए, मेरे पास एक प्रोजेक्ट है, जहां आधे ऑडियो बफ़र्स में केवल 4-बाइट मैजिक वैल्यू होती है, क्योंकि यह बदलने से बहुत आसान था कि एक लाइब्रेरी ने अपने ऑडियो कोडेक्स को कैसे लागू किया।)

विशिष्ट कोड के बिना विशिष्ट सलाह देना कठिन है।


3

स्वचालित परीक्षण। आपको टीडीडी जेडलॉट होने की आवश्यकता नहीं है, न ही आपको 100% कवरेज की आवश्यकता है, लेकिन स्वचालित परीक्षण वे हैं जो आपको आत्मविश्वास से बदलाव करने की अनुमति देते हैं। इसके अलावा, ऐसा लगता है कि आपके पास बहुत उच्च युग्मन के साथ एक डिजाइन है; आपको SOLID सिद्धांतों के बारे में पढ़ना चाहिए, जो विशेष रूप से सॉफ़्टवेयर डिज़ाइन में इस तरह के मुद्दे को संबोधित करने के लिए तैयार किए गए हैं।

मैं इन किताबों की भी सिफारिश करूंगा।

  • विरासत कोड , पंख के साथ प्रभावी ढंग से काम करना
  • रिफैक्टरिंग , फाउलर
  • बढ़ते ऑब्जेक्ट-ओरिएंटेड सॉफ्टवेयर, गाइडेड बाय टेस्ट्स , फ्रीमैन और प्रिस
  • क्लीन कोड , मार्टिन

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

6
यदि मैं एक भारी उपयोग किए गए इंटरफ़ेस को पुनःप्राप्त कर रहा हूं, तो मैं एक शिम जोड़ता हूं। यह शिम डिफॉल्टिंग को हैंडल करता है, ताकि लीगेसी कॉल काम करती रहे। मैं शिम के पीछे इंटरफेस पर काम करता हूं, फिर, जब मैं इसके साथ किया जाता हूं, तो मैं शिम के बजाय फिर से इंटरफ़ेस का उपयोग करने के लिए कक्षाएं बदलना शुरू कर देता हूं।
आषाढ़

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

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

3
@DeadMG उस मामले में, मुझे लगता है कि आप जो कर रहे हैं, उसे यथोचित नहीं कहा जा सकता है, जिसका मूल बिंदु बहुत ही सरल चरणों की एक श्रृंखला के रूप में डिज़ाइन परिवर्तन लागू करना है।
जूल्स

3

क्या यह सिर्फ मेरी पिछली कक्षाओं का एक लक्षण है जो एक दूसरे पर बहुत कसकर निर्भर करता है?

सबसे शायद हाँ। यद्यपि आप आवश्यकताओं को पर्याप्त रूप से बदलने के बजाय एक अच्छा और साफ कोड आधार के साथ समान प्रभाव प्राप्त कर सकते हैं

मैं भविष्य में इस तरह के कैस्केडिंग रिफैक्टरिंग से कैसे बच सकता हूं?

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

उस विधि को "मिकादो विधि" नाम दिया गया है और यह इस तरह काम करती है:

  1. आप जिस उद्देश्य को हासिल करना चाहते हैं उसे कागज के एक टुकड़े पर लिख लें

  2. सबसे सरल परिवर्तन करें जो आपको उस दिशा में ले जाए।

  3. जांच लें कि यह कंपाइलर और आपके परीक्षण सूट का उपयोग करके काम करता है या नहीं। यदि यह चरण 7 के साथ जारी रहता है, तो चरण 4 के साथ जारी रखें।

  4. अपने कागज पर उन चीजों पर ध्यान दें जो आपके वर्तमान परिवर्तन को काम करने के लिए बदलने की आवश्यकता है। अपने वर्तमान कार्य से, नए लोगों के लिए तीर बनाएँ।

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

  6. कार्यों में से एक को चुनें, जिसमें कोई आउटगोइंग त्रुटियां नहीं हैं (कोई ज्ञात निर्भरता नहीं) और 2 पर लौटें।

  7. परिवर्तन के लिए, कागज पर कार्य को पार करें, ऐसा कार्य चुनें जिसमें कोई आउटगोइंग त्रुटियां नहीं हैं (कोई ज्ञात निर्भरता नहीं) और 2 पर वापस लौटें।

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


2

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

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


2

... मैंने फीचर जोड़ने के लिए प्रोजेक्ट को फिर से शुरू किया।

जैसा कि @Jules, Refactoring और सुविधाओं को जोड़ना दो बहुत अलग चीजें हैं।

  • Refactoring अपने व्यवहार में बदलाव किए बिना कार्यक्रम की संरचना को बदलने के बारे में है।
  • दूसरी ओर, एक विशेषता जोड़ना, अपने व्यवहार को बढ़ा रहा है।

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

मुझे इसे समायोजित करने के लिए एक मामूली इंटरफ़ेस परिवर्तन करने की आवश्यकता थी

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

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

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


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

... वास्तव में, कैस्केडिंग कोड संशोधनों से बचने का सबसे अच्छा तरीका ठीक-ठीक अच्छा इंटरफेस है। ;)


-1

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


1
ऐसा लगता है कि किए गए अंकों से अधिक कुछ भी नहीं दिया जा रहा है और पहले 9 जवाबों में समझाया गया है
gnat

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