2011-04-02 16 views
17

मैं के बारे में हमारे codebase का एक प्रमुख पुनर्रचना योजना बना शुरू करने के लिए कर रहा हूँ, और मैं (मैं https://stackoverflow.com/questions/108141/how-do-i-work-effectively-with-very-messy-legacy-code जैसे Strategy for large scale refactoring समान विषयों पर काफी कुछ चर्चा,, देखा है, लेकिन मैं कुछ है कुछ प्रश्नों के कुछ राय और उत्तर प्राप्त करना चाहते हैं विशिष्ट प्रश्न (नीचे):एक बड़ी रिफैक्टरिंग परियोजना के बारे में कैसे जाना है?

हम एक जटिल अनुप्रयोग विकसित करते हैं। कुछ 25 डेवलपर कोडबेस काम कर रहे हैं। उत्पाद में कुल आदमी वर्ष लगभग 150 हैं। वर्तमान कोडबेस एक एकल परियोजना है, चींटी के साथ। परियोजना मैं आरंभ करने कर रहा हूँ के उच्च स्तर लक्ष्य अपनी विभिन्न आधारभूत संरचनाओं और अनुप्रयोगी घटकों में codebase modularize है। वर्तमान में विभिन्न तार्किक घटकों के बीच कोई अच्छा जुदाई नहीं है, तो यह किसी भी मो कि स्पष्ट है अलगावकरण प्रयास को कुछ एपीआई परिभाषाओं और अलगाव को सक्षम करने के लिए गंभीर असंगतता को शामिल करने की आवश्यकता होगी। गुणवत्ता मानकों कम हैं - लगभग कोई परीक्षण नहीं है, और निश्चित रूप से निर्माण प्रक्रिया के हिस्से के रूप में कोई परीक्षण नहीं चल रहा है।

एक अन्य महत्वपूर्ण बिंदु इस परियोजना सक्रिय उत्पाद विकास और संस्करणों ग्राहकों के लिए भेज दिया जा रहा करने के लिए समानांतर में जगह लेने के लिए की जरूरत है।

परियोजना के लक्ष्य:

  • विभिन्न परियोजनाओं भर में बुनियादी सुविधाओं से
  • अलग आवेदन घटकों के पुन: उपयोग की अनुमति देते हैं, और उन्हें विकसित करने के लिए स्वतंत्र रूप से
  • testability में सुधार (बनाने एपीआई द्वारा)
  • डेवलपर्स को आसान बनाने के लिए अनुमति देते हैं 'देव env (कम कोड चेक आउट और संकलित)

मेरा हालांकि टीएस और प्रश्न:

  1. परियोजना के लक्ष्यों के बारे में आपके विचार क्या हैं? आप कुछ भी बदल जाएगा?
  2. आप ऐसी परियोजनाओं के साथ अनुभव है? कुछ सिफारिशें क्या होंगी?
  3. मैं परीक्षण की कमी के साथ बहुत चिंतित हूं - इसलिए नियंत्रण की कमी मुझे पता करने के लिए कि रिफैक्टरिंग प्रक्रिया कुछ भी तोड़ने नहीं है के रूप में मैं जाना। यह एक पकड़ 22 है, क्योंकि इस परियोजना के लक्ष्यों में से एक है हमारे कोड को अधिक परीक्षण योग्य बनाना ...
  4. मैं माइकल फेदर्स Working Effectively With Legacy Code से बहुत प्रभावित था। इसके अनुसार एक नीचे से ऊपर दृष्टिकोण मेरी समस्या को हल करने तरीका है - सिर codebase में पहले कूद नहीं करते हैं और इसे ठीक करने की कोशिश है, बल्कि कई महीनों के लिए नए कोड के आसपास इकाई परीक्षण जोड़कर छोटे शुरू, और देखते हैं कि कोड (और टीम) बहुत बेहतर हो जाता है, जहां तक ​​अमूर्तताएं उभरती हैं, एपीआई सतह पर आ जाएंगी, और अनिवार्य रूप से - मॉड्यूलरेशन स्वयं ही हो रहा है। क्या किसी को ऐसी दिशा के साथ अनुभव है? जैसा कि इस विषय पर कई अन्य प्रश्नों में देखा गया है - यहां मुख्य समस्या प्रबंधकीय अविश्वास है। "वर्ग द्वारा परीक्षण कक्षा (और ऐसा करने में बहुत समय व्यतीत करना) हमें एक स्थिर प्रणाली में लाने के लिए कैसे है? यह एक अच्छा सिद्धांत है जो वास्तविक जीवन में काम नहीं करता है"। इसे बेचने पर कोई सुझाव?

उत्तर

12

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

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

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

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

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

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

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

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

2

यह वही है जो हम पिछले कुछ सालों से वेब 2 प्रोजेक्ट के लिए कर रहे हैं .. हमने मौजूदा सिस्टम (डॉटप्रोजेक्ट) से फोर्क किया है जिसमें उच्च चक्रीय जटिलता जैसे कम मीट्रिक थे (निम्न: 17, औसत: 27, उच्च: 1 9 55), बहुत सारे डुप्लिकेट कोड (कुल कोड का 8%), और शून्य परीक्षण।

विभाजन के बाद से, हमने डुप्लिकेट कोड (2.1% समग्र) कम कर दिया है, कुल कोड (200kloc से 155kloc) को कम किया है, लगभग 500 यूनिट परीक्षण और बेहतर चक्रवात जटिलता (निम्न: 1, औसत: 11, उच्च : 145 एम)। हां, हमारे पास अभी भी जाने का एक तरीका है।

हमारी रणनीति अपनी स्लाइडों में यहाँ में विस्तृत है: http://caseysoftware.com/blog/phpbenelux-2011-recap - परियोजना ट्राइएज & रिकवरी; और यहां: http://www.phparch.com/2010/11/codeworks-2010-slides/ - यूनिट परीक्षण रणनीतियां; और इस तरह की विभिन्न पोस्टों में: http://caseysoftware.com/blog/technical-debt-doesn039t-disappear

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

शुभकामनाएं।

3

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

केवल दो तरीके हैं।

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

  • रिफैक्टरिंग प्रक्रिया स्वचालित करें। यदि आप भरोसेमंद स्वचालित परिवर्तन लागू करते हैं, तो आप तर्क दे सकते हैं (अक्सर असफल) कि refactored कोड मूल सिस्टम फ़ंक्शन को संरक्षित करता है। असुरक्षित तर्क को हरा करने का तरीका उन परीक्षणों को लिखना है (पहली विधि देखें) और आवेदन और परीक्षणों में रीफैक्टरिंग प्रक्रिया लागू करें; चूंकि एप्लिकेशन संरचनाओं को बदलता है, परीक्षणों को भी बदलना पड़ता है। लेकिन वे स्वचालित मशीनरी के दृष्टिकोण से सिर्फ आवेदन कोड हैं।

बहुत से लोग उत्तरार्द्ध नहीं करते हैं; आपको ऐसे टूल कहां मिलते हैं जो ऐसी चीजें कर सकते हैं?

वास्तव में, ऐसे उपकरण मौजूद हैं। उन्हें program transformation tools कहा जाता है और कोड पर बड़े पैमाने पर परिवर्तन करने के लिए उपयोग किया जाता है। इन्हें बड़े पैमाने पर रीफैक्टरिंग के लिए टूल के रूप में सोचें; पैमाने के कारण, वे इंटरेक्टिव नहीं होते हैं।

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

मुझे केवल ऐसे 3 टूल हैं जो वास्तविक कोड पर काम करने का मौका रखते हैं: TXL, Stratego/XT, और हमारे टूल, DMS Software Reengineering Toolkit। पहले दो अकादमिक उत्पाद हैं (हालांकि अतीत में वाणिज्यिक गतिविधियों के लिए TXL का उपयोग किया गया है); डीएमएस वाणिज्यिक है।

डीएमएस का उपयोग विभिन्न प्रकार के बड़े पैमाने पर सॉफ्टवेयर एनीसिस और बड़े पैमाने पर परिवर्तन कार्यों के लिए किया गया है। एक कार्य automated translation between languages for the B-2 Stealth Bomber था। एक और, आपकी रिफैक्टरिंग समस्या के बहुत करीब, घटक के लिए एक बड़े पैमाने पर घटक-आधारित सिस्टम सी ++ के स्वचालित आर्किटेक्चरिंग था, एक विरासत मालिकाना आरटीओएस से घटक के व्यवस्थित नियमों के बारे में अपने idiosyncratic नियमों के साथ, कॉरबा/आरटी में जिसमें घटक एपीआई था विज्ञापन संरचनाओं से CORBA- शैली पहलू और ग्रहण इंटरफेस के साथ-साथ विरासत आरटीओएस सेवाओं के स्थान पर कॉरबा/आरटी सेवाओं का उपयोग करने के लिए बदला जा सकता है। (इन कार्यों को वास्तविक स्मार्ट और डीएमएस-समझदार लोगों द्वारा वास्तविक प्रयास के 1-2 व्यक्ति-वर्ष के साथ किया गया था)।

अभी भी परीक्षण-निर्माण समस्या है (ऊपर दिए गए दोनों उदाहरणों में पहले से ही महान सिस्टम परीक्षण थे) .. यहां मैं एक अंग पर बाहर जा रहा हूं। मेरा मानना ​​है कि फ़ंक्शन इनपुट-आउटपुट परिणामों को एकत्रित करने के लिए चल रहे कोड को मापकर परीक्षण पीढ़ी को स्वचालित करने के लिए ऐसे टूल प्राप्त करने में आशा है।हमने स्रोत कोड के लिए सभी प्रकार के वाद्ययंत्र बनाए हैं (जाहिर है आपको इसे उपकरण के बाद संकलित करना होगा) और लगता है कि हम जानते हैं कि यह कैसे करें। YMMV।

वहाँ कुछ आप करते हैं जो काफी कम महत्वाकांक्षी है: कोड के पुन: प्रयोज्य भागों की पहचान, जानने क्या कोड में पुन: उपयोग किया गया है द्वारा। अधिकांश सॉफ़्टवेयर सिस्टम में बहुत सारे क्लोन कोड होते हैं (हमारा अनुभव 10-20% है [और मैं दूसरे उत्तरों में छोटी संख्याओं की PHP रिपोर्ट से हैरान हूं; मुझे संदेह है कि वे एक कमजोर क्लोन डिटेक्टर का उपयोग कर रहे हैं)। क्लोन कोड एप्लिकेशन सॉफ़्टवेयर में अनुपलब्ध अमूर्तता का संकेत है। यदि आप क्लोन पा सकते हैं और देख सकते हैं कि वे कैसे भिन्न होते हैं, तो आप उन्हें आसानी से देख सकते हैं कि उन्हें स्पष्ट रूप से और पुन: प्रयोज्य बनाने के लिए उन्हें कैसे कार्य (या जो भी) में सारणित किया जाए।

Salion इंक did clone detection and abstraction। पेपर अमूर्त गतिविधि का पता नहीं लगाता है; वास्तव में क्या सैलियन पता चला क्लोन की आवधिक समीक्षा थी, और समेकित लोगों के मैन्युअल उपचार या जो (अक्सर पुस्तकालय) विधियों में समझ में आया था। शुद्ध परिणाम कोड आधार वास्तव में आकार में घट गया था और प्रोग्रामर अधिक प्रभावी हो गए क्योंकि उनके पास बेहतर ("अधिक पुन: प्रयोज्य") पुस्तकालय थे।

वे एक गाइड के रूप में कार्यक्रम सिंटेक्स के उपयोग से क्लोन ढूंढने की हमारी CloneDR, एक उपकरण का इस्तेमाल किया। क्लोनडीआर को सटीक क्लोन और नज़दीकी मिस (पहचानकर्ताओं या बयानों के प्रतिस्थापन) मिलते हैं और लेआउट और टिप्पणियों के बावजूद क्लोन लोकेशन और क्लोन पैरामीकरण की एक विशिष्ट सूची प्रदान करते हैं। आप लिंक पर कई भाषाओं के लिए क्लोन रिपोर्ट देख सकते हैं। (मैं अपने कई टोपी के बीच originator and author of CloneDR हूँ)।

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