लेगसी कोड रिफॅक्टरिंगसाठी एक व्यावहारिक मार्गदर्शक, ज्यात ओळख, प्राधान्यक्रम, तंत्र आणि आधुनिकीकरण व देखभालीसाठी सर्वोत्तम पद्धतींचा समावेश आहे.
अवघड कोडवर मात करणे: लेगसी कोडसाठी रिफॅक्टरिंग स्ट्रॅटेजीज
लेगसी कोड. हा शब्द ऐकताच अनेकदा अस्ताव्यस्त, डॉक्युमेंटेशन नसलेल्या सिस्टीम्स, नाजूक डिपेंडेंसीज आणि एक प्रकारची भीती मनात येते. जगभरातील अनेक डेव्हलपर्सना या सिस्टीम्सची देखभाल आणि विकास करण्याचे आव्हान पेलावे लागते, ज्या अनेकदा व्यवसायाच्या दृष्टीने अत्यंत महत्त्वाच्या असतात. हे सर्वसमावेशक मार्गदर्शक लेगसी कोडला रिफॅक्टर करण्यासाठी व्यावहारिक स्ट्रॅटेजीज प्रदान करते, ज्यामुळे निराशेचे कारण बनलेली ही गोष्ट आधुनिकीकरण आणि सुधारणेच्या संधीत बदलते.
लेगसी कोड म्हणजे काय?
रिफॅक्टरिंग तंत्रांमध्ये जाण्यापूर्वी, "लेगसी कोड" म्हणजे काय हे परिभाषित करणे आवश्यक आहे. हा शब्द फक्त जुन्या कोडसाठी वापरला जात असला तरी, त्याची अधिक अचूक व्याख्या त्याच्या देखभालक्षमतेवर (maintainability) लक्ष केंद्रित करते. मायकल फेदर्स यांनी त्यांच्या "वर्किंग इफेक्टिव्हली विथ लेगसी कोड" या प्रसिद्ध पुस्तकात लेगसी कोडची व्याख्या 'टेस्ट्स नसलेला कोड' अशी केली आहे. या टेस्ट्सच्या अभावामुळे, कोडमध्ये सुरक्षितपणे बदल करणे आणि नवीन चुका (regressions) टाळणे कठीण होते. तथापि, लेगसी कोडमध्ये इतर वैशिष्ट्ये देखील असू शकतात:
- डॉक्युमेंटेशनचा अभाव: मूळ डेव्हलपर्स पुढे निघून गेलेले असू शकतात, आणि त्यांनी सिस्टीमचे आर्किटेक्चर, डिझाइनमधील निर्णय किंवा मूलभूत कार्यप्रणाली समजावून सांगणारे कोणतेही डॉक्युमेंटेशन मागे ठेवलेले नसते.
- गुंतागुंतीचे डिपेंडेंसीज: कोड घट्टपणे जोडलेला (tightly coupled) असू शकतो, ज्यामुळे सिस्टीमच्या इतर भागांवर परिणाम न करता वैयक्तिक घटकांना वेगळे करणे आणि सुधारित करणे कठीण होते.
- जुने तंत्रज्ञान: कोड जुन्या प्रोग्रामिंग भाषा, फ्रेमवर्क किंवा लायब्ररीज वापरून लिहिलेला असू शकतो ज्यांना आता सक्रियपणे सपोर्ट दिला जात नाही, ज्यामुळे सुरक्षिततेचे धोके निर्माण होतात आणि आधुनिक साधनांचा वापर मर्यादित होतो.
- खराब कोड गुणवत्ता: कोडमध्ये डुप्लिकेट कोड, लांबलचक मेथड्स आणि इतर 'कोड स्मेल्स' असू शकतात ज्यामुळे तो समजायला आणि सांभाळायला कठीण जातो.
- ठिसूळ डिझाइन: वरवर पाहता लहान वाटणाऱ्या बदलांचे अनपेक्षित आणि दूरगामी परिणाम होऊ शकतात.
हे लक्षात घेणे महत्त्वाचे आहे की लेगसी कोड मूळतः वाईट नसतो. तो अनेकदा एक महत्त्वपूर्ण गुंतवणूक दर्शवतो आणि त्यात मौल्यवान डोमेन ज्ञानाचा समावेश असतो. रिफॅक्टरिंगचा उद्देश या मूल्याचे जतन करणे आणि त्याच वेळी कोडची देखभालक्षमता, विश्वसनीयता आणि कार्यक्षमता सुधारणे हा आहे.
लेगसी कोड रिफॅक्टर का करावा?
लेगसी कोड रिफॅक्टर करणे एक आव्हानात्मक काम असू शकते, परंतु त्याचे फायदे अनेकदा आव्हानांपेक्षा जास्त असतात. रिफॅक्टरिंगमध्ये गुंतवणूक करण्याची काही प्रमुख कारणे येथे आहेत:
- सुधारित देखभालक्षमता: रिफॅक्टरिंगमुळे कोड समजणे, बदलणे आणि डीबग करणे सोपे होते, ज्यामुळे चालू देखभालीसाठी लागणारा खर्च आणि प्रयत्न कमी होतात. जागतिक स्तरावरील टीम्ससाठी हे विशेषतः महत्त्वाचे आहे, कारण यामुळे विशिष्ट व्यक्तींवरील अवलंबित्व कमी होते आणि ज्ञान वाटून घेण्यास प्रोत्साहन मिळते.
- टेक्निकल डेटमध्ये घट: टेक्निकल डेट म्हणजे भविष्यात जास्त वेळ लागणाऱ्या चांगल्या पद्धतीऐवजी सध्या सोपा उपाय निवडल्यामुळे नंतर करावा लागणारा कामाचा खर्च. रिफॅक्टरिंग हे कर्ज फेडण्यास मदत करते, ज्यामुळे कोडबेसचे आरोग्य सुधारते.
- वाढीव विश्वसनीयता: 'कोड स्मेल्स' दूर करून आणि कोडची रचना सुधारून, रिफॅक्टरिंगमुळे बग्सचा धोका कमी होऊ शकतो आणि सिस्टीमची एकूण विश्वसनीयता सुधारू शकते.
- वाढीव कार्यक्षमता: रिफॅक्टरिंगमुळे कार्यक्षमतेतील अडथळे (performance bottlenecks) ओळखून ते दूर करता येतात, ज्यामुळे जलद एक्झिक्युशन वेळ आणि सुधारित प्रतिसाद मिळतो.
- सोपे इंटिग्रेशन: रिफॅक्टरिंगमुळे लेगसी सिस्टीमला नवीन सिस्टीम्स आणि तंत्रज्ञानाशी जोडणे सोपे होते, ज्यामुळे नावीन्य आणि आधुनिकीकरणाला चालना मिळते. उदाहरणार्थ, युरोपियन ई-कॉमर्स प्लॅटफॉर्मला नवीन पेमेंट गेटवेशी इंटिग्रेट करण्याची आवश्यकता असू शकते जो वेगळा API वापरतो.
- डेव्हलपरच्या मनोबलात सुधारणा: स्वच्छ, सुव्यवस्थित कोडसोबत काम करणे डेव्हलपर्ससाठी अधिक आनंददायक आणि उत्पादक असते. रिफॅक्टरिंगमुळे मनोबल वाढू शकते आणि नवीन प्रतिभा आकर्षित होऊ शकते.
रिफॅक्टरिंगसाठी योग्य कोड ओळखणे
सर्वच लेगसी कोडला रिफॅक्टर करण्याची गरज नसते. खालील घटकांवर आधारित रिफॅक्टरिंगच्या प्रयत्नांना प्राधान्य देणे महत्त्वाचे आहे:
- बदलांची वारंवारता: ज्या कोडमध्ये वारंवार बदल केले जातात, तो रिफॅक्टरिंगसाठी एक प्रमुख उमेदवार आहे, कारण देखभालक्षमतेतील सुधारणांचा विकास उत्पादकतेवर महत्त्वपूर्ण परिणाम होईल.
- गुंतागुंत: जो कोड गुंतागुंतीचा आणि समजण्यास कठीण आहे, त्यात बग्स असण्याची शक्यता जास्त असते आणि तो सुरक्षितपणे बदलणे कठीण असते.
- बग्सचा प्रभाव: जो कोड व्यवसायाच्या कामकाजासाठी महत्त्वाचा आहे किंवा ज्यामुळे महागड्या चुका होण्याचा धोका जास्त आहे, त्याला रिफॅक्टरिंगसाठी प्राधान्य दिले पाहिजे.
- कार्यक्षमतेतील अडथळे: जो कोड कार्यक्षमतेत अडथळा म्हणून ओळखला जातो, त्याला कार्यक्षमता सुधारण्यासाठी रिफॅक्टर केले पाहिजे.
- कोड स्मेल्स (Code Smells): लांबलचक मेथड्स, मोठे क्लासेस, डुप्लिकेट कोड आणि फीचर एनव्ही (feature envy) यांसारख्या सामान्य कोड स्मेल्सवर लक्ष ठेवा. हे त्या क्षेत्रांचे सूचक आहेत जिथे रिफॅक्टरिंगमुळे फायदा होऊ शकतो.
उदाहरण: एका जागतिक लॉजिस्टिक्स कंपनीची कल्पना करा, जिच्याकडे शिपमेंट्स व्यवस्थापित करण्यासाठी एक लेगसी सिस्टीम आहे. शिपिंग खर्चाची गणना करणारे मॉड्युल बदलणारे नियम आणि इंधनाच्या किमतींमुळे वारंवार अपडेट केले जाते. हे मॉड्युल रिफॅक्टरिंगसाठी एक प्रमुख उमेदवार आहे.
रिफॅक्टरिंगची तंत्रे
अनेक रिफॅक्टरिंग तंत्रे उपलब्ध आहेत, प्रत्येक तंत्र विशिष्ट कोड स्मेल दूर करण्यासाठी किंवा कोडच्या विशिष्ट पैलूंना सुधारण्यासाठी डिझाइन केलेले आहे. येथे काही सामान्यतः वापरली जाणारी तंत्रे आहेत:
मेथड्सची रचना करणे
ही तंत्रे मोठ्या, गुंतागुंतीच्या मेथड्सना लहान, अधिक व्यवस्थापनीय मेथड्समध्ये विभागण्यावर लक्ष केंद्रित करतात. यामुळे वाचनीयता सुधारते, डुप्लिकेशन कमी होते आणि कोडची तपासणी करणे सोपे होते.
- एक्स्ट्रॅक्ट मेथड (Extract Method): यामध्ये कोडचा एक विशिष्ट कार्य करणारा ब्लॉक ओळखून तो एका नवीन मेथडमध्ये हलवणे समाविष्ट आहे.
- इनलाइन मेथड (Inline Method): यामध्ये मेथड कॉलच्या जागी मेथडची बॉडी ठेवली जाते. हे तेव्हा वापरावे जेव्हा मेथडचे नाव तिच्या बॉडीइतकेच स्पष्ट असेल, किंवा जेव्हा तुम्ही एक्स्ट्रॅक्ट मेथड वापरणार असाल परंतु सध्याची मेथड खूपच लहान असेल.
- रिप्लेस टेम्प विथ क्वेरी (Replace Temp with Query): यामध्ये एका तात्पुरत्या व्हेरिएबलच्या जागी एक मेथड कॉल वापरला जातो जो गरजेनुसार व्हेरिएबलचे मूल्य मोजतो.
- इंट्रोड्यूस एक्सप्लेनिंग व्हेरिएबल (Introduce Explaining Variable): याचा वापर एखाद्या एक्सप्रेशनचा निकाल एका वर्णनात्मक नावाच्या व्हेरिएबलला देण्यासाठी केला जातो, ज्यामुळे त्याचा उद्देश स्पष्ट होतो.
ऑब्जेक्ट्समध्ये फीचर्स हलवणे
ही तंत्रे जबाबदाऱ्या योग्य ठिकाणी हलवून क्लासेस आणि ऑब्जेक्ट्सच्या डिझाइनमध्ये सुधारणा करण्यावर लक्ष केंद्रित करतात.
- मूव्ह मेथड (Move Method): यामध्ये एका मेथडला एका क्लासमधून दुसऱ्या क्लासमध्ये हलवणे समाविष्ट आहे जिथे ती तार्किकदृष्ट्या योग्य आहे.
- मूव्ह फील्ड (Move Field): यामध्ये एका फील्डला एका क्लासमधून दुसऱ्या क्लासमध्ये हलवणे समाविष्ट आहे जिथे ती तार्किकदृष्ट्या योग्य आहे.
- एक्स्ट्रॅक्ट क्लास (Extract Class): यामध्ये सध्याच्या क्लासमधून काढलेल्या जबाबदाऱ्यांच्या सुसंगत संचातून एक नवीन क्लास तयार करणे समाविष्ट आहे.
- इनलाइन क्लास (Inline Class): जेव्हा एखादा क्लास त्याच्या अस्तित्वासाठी पुरेसे काम करत नाही, तेव्हा त्याला दुसऱ्या क्लासमध्ये विलीन करण्यासाठी याचा वापर करा.
- हाइड डेलीगेट (Hide Delegate): क्लायंट आणि डेलीगेटमधील कपलिंग कमी करण्यासाठी, क्लायंटकडून डेलीगेशन लॉजिक लपवण्यासाठी सर्व्हरमध्ये मेथड्स तयार करणे.
- रिमूव्ह मिडल मॅन (Remove Middle Man): जर एखादा क्लास आपले बहुतेक काम डेलीगेट करत असेल, तर हे मधल्या माणसाला काढून टाकण्यास मदत करते.
- इंट्रोड्यूस फॉरेन मेथड (Introduce Foreign Method): सर्व्हर क्लासमधून खरोखर आवश्यक असलेल्या पण ऍक्सेसच्या अभावामुळे किंवा सर्व्हर क्लासमधील नियोजित बदलांमुळे सुधारित करता न येणाऱ्या फीचर्ससह क्लायंटला सेवा देण्यासाठी क्लायंट क्लासमध्ये एक मेथड जोडते.
- इंट्रोड्यूस लोकल एक्सटेन्शन (Introduce Local Extension): एक नवीन क्लास तयार करतो ज्यात नवीन मेथड्स असतात. जेव्हा तुम्ही क्लासच्या स्त्रोतावर नियंत्रण ठेवू शकत नाही आणि थेट वर्तन जोडू शकत नाही तेव्हा उपयुक्त.
डेटा संघटित करणे
ही तंत्रे डेटा संग्रहित आणि ऍक्सेस करण्याच्या पद्धतीत सुधारणा करण्यावर लक्ष केंद्रित करतात, ज्यामुळे तो समजणे आणि बदलणे सोपे होते.
- रिप्लेस डेटा व्हॅल्यू विथ ऑब्जेक्ट (Replace Data Value with Object): यामध्ये एका साध्या डेटा व्हॅल्यूच्या जागी संबंधित डेटा आणि वर्तन समाविष्ट करणारे ऑब्जेक्ट ठेवणे.
- चेंज व्हॅल्यू टू रेफरन्स (Change Value to Reference): जेव्हा अनेक ऑब्जेक्ट्स समान व्हॅल्यू शेअर करतात, तेव्हा व्हॅल्यू ऑब्जेक्टला रेफरन्स ऑब्जेक्टमध्ये बदलणे.
- चेंज युनिडायरेक्शनल असोसिएशन टू बायडायरेक्शनल (Change Unidirectional Association to Bidirectional): दोन क्लासेसमध्ये द्विदिशात्मक लिंक तयार करते जिथे फक्त एक-मार्गी लिंक अस्तित्वात आहे.
- चेंज बायडायरेक्शनल असोसिएशन टू युनिडायरेक्शनल (Change Bidirectional Association to Unidirectional): दोन-मार्गी संबंधांना एक-मार्गी बनवून असोसिएशन सोपे करते.
- रिप्लेस मॅजिक नंबर विथ सिम्बॉलिक कॉन्स्टंट (Replace Magic Number with Symbolic Constant): यामध्ये थेट व्हॅल्यूजच्या जागी नावाचे कॉन्स्टंट वापरले जातात, ज्यामुळे कोड समजणे आणि देखभाल करणे सोपे होते.
- एनकॅप्सुलेट फील्ड (Encapsulate Field): फील्ड ऍक्सेस करण्यासाठी गेटर आणि सेटर मेथड प्रदान करते.
- एनकॅप्सुलेट कलेक्शन (Encapsulate Collection): कलेक्शनमधील सर्व बदल मालक क्लासमधील काळजीपूर्वक नियंत्रित केलेल्या मेथड्सद्वारेच होतील याची खात्री करते.
- रिप्लेस रेकॉर्ड विथ डेटा क्लास (Replace Record with Data Class): रेकॉर्डच्या संरचनेशी जुळणारे फील्ड आणि ऍक्सेसर मेथड्ससह एक नवीन क्लास तयार करते.
- रिप्लेस टाइप कोड विथ क्लास (Replace Type Code with Class): जेव्हा टाइप कोडमध्ये मर्यादित, ज्ञात संभाव्य व्हॅल्यूजचा संच असतो तेव्हा एक नवीन क्लास तयार करा.
- रिप्लेस टाइप कोड विथ सबक्लासेस (Replace Type Code with Subclasses): जेव्हा टाइप कोड व्हॅल्यू क्लासच्या वर्तनावर परिणाम करते.
- रिप्लेस टाइप कोड विथ स्टेट/स्ट्रॅटेजी (Replace Type Code with State/Strategy): जेव्हा टाइप कोड व्हॅल्यू क्लासच्या वर्तनावर परिणाम करते, परंतु सबक्लासिंग योग्य नसते.
- रिप्लेस सबक्लास विथ फील्ड्स (Replace Subclass with Fields): एक सबक्लास काढून टाकतो आणि सुपरक्लासमध्ये सबक्लासच्या विशिष्ट गुणधर्मांचे प्रतिनिधित्व करणारी फील्ड्स जोडतो.
कंडिशनल एक्सप्रेशन्स सोपे करणे
कंडिशनल लॉजिक लवकरच गुंतागुंतीचे होऊ शकते. ही तंत्रे स्पष्टता आणण्याचा आणि सुलभ करण्याचा उद्देश ठेवतात.
- डीकंपोज कंडिशनल (Decompose Conditional): यामध्ये एका गुंतागुंतीच्या कंडिशनल स्टेटमेंटला लहान, अधिक व्यवस्थापनीय तुकड्यांमध्ये विभागणे समाविष्ट आहे.
- कन्सॉलिडेट कंडिशनल एक्सप्रेशन (Consolidate Conditional Expression): यामध्ये अनेक कंडिशनल स्टेटमेंट्सना एकाच, अधिक संक्षिप्त स्टेटमेंटमध्ये एकत्र करणे समाविष्ट आहे.
- कन्सॉलिडेट डुप्लिकेट कंडिशनल फ्रॅगमेंट्स (Consolidate Duplicate Conditional Fragments): यामध्ये कंडिशनल स्टेटमेंटच्या अनेक शाखांमध्ये डुप्लिकेट असलेल्या कोडला कंडिशनलच्या बाहेर हलवणे समाविष्ट आहे.
- रिमूव्ह कंट्रोल फ्लॅग (Remove Control Flag): लॉजिकच्या प्रवाहावर नियंत्रण ठेवण्यासाठी वापरल्या जाणाऱ्या बुलियन व्हेरिएबल्स काढून टाका.
- रिप्लेस नेस्टेड कंडिशनल विथ गार्ड क्लॉजेस (Replace Nested Conditional with Guard Clauses): सर्व विशेष प्रकरणे वर ठेवून आणि त्यापैकी कोणतेही खरे असल्यास प्रक्रिया थांबवून कोड अधिक वाचनीय बनवते.
- रिप्लेस कंडिशनल विथ पॉलिमॉर्फिझम (Replace Conditional with Polymorphism): यामध्ये कंडिशनल लॉजिकच्या जागी पॉलिमॉर्फिझम वापरला जातो, ज्यामुळे वेगवेगळे ऑब्जेक्ट्स वेगवेगळी प्रकरणे हाताळू शकतात.
- इंट्रोड्यूस नल ऑब्जेक्ट (Introduce Null Object): नल व्हॅल्यू तपासण्याऐवजी, एक डीफॉल्ट ऑब्जेक्ट तयार करा जो डीफॉल्ट वर्तन प्रदान करतो.
- इंट्रोड्यूस असर्शन (Introduce Assertion): अपेक्षांची तपासणी करणारी टेस्ट तयार करून अपेक्षा स्पष्टपणे डॉक्युमेंट करा.
मेथड कॉल्स सोपे करणे
- रिनेम मेथड (Rename Method): हे स्पष्ट वाटू शकते, परंतु कोड स्पष्ट करण्यासाठी अत्यंत उपयुक्त आहे.
- ॲड पॅरामीटर (Add Parameter): मेथड सिग्नेचरमध्ये माहिती जोडल्याने मेथड अधिक लवचिक आणि पुन्हा वापरण्यायोग्य बनते.
- रिमूव्ह पॅरामीटर (Remove Parameter): जर पॅरामीटर वापरला जात नसेल, तर इंटरफेस सोपा करण्यासाठी तो काढून टाका.
- सेपरेट क्वेरी फ्रॉम मॉडिफायर (Separate Query from Modifier): जर एखादी मेथड व्हॅल्यू बदलते आणि परत करते, तर तिला दोन वेगळ्या मेथड्समध्ये विभाजित करा.
- पॅरामीटराइज मेथड (Parameterize Method): समान मेथड्सना एकाच मेथडमध्ये एकत्र करण्यासाठी याचा वापर करा, ज्यात एक पॅरामीटर वर्तनात बदल करतो.
- रिप्लेस पॅरामीटर विथ एक्सप्लिसिट मेथड्स (Replace Parameter with Explicit Methods): पॅरामीटराइजच्या उलट करा - एकाच मेथडला अनेक मेथड्समध्ये विभाजित करा, जिथे प्रत्येक मेथड पॅरामीटरच्या विशिष्ट व्हॅल्यूचे प्रतिनिधित्व करते.
- प्रिझर्व होल ऑब्जेक्ट (Preserve Whole Object): मेथडला काही विशिष्ट डेटा आयटम पास करण्याऐवजी, संपूर्ण ऑब्जेक्ट पास करा जेणेकरून मेथडला त्याच्या सर्व डेटामध्ये प्रवेश मिळेल.
- रिप्लेस पॅरामीटर विथ मेथड (Replace Parameter with Method): जर एखादी मेथड नेहमीच फील्डमधून मिळवलेल्या समान व्हॅल्यूसह कॉल केली जात असेल, तर मेथडच्या आत पॅरामीटर व्हॅल्यू मिळवण्याचा विचार करा.
- इंट्रोड्यूस पॅरामीटर ऑब्जेक्ट (Introduce Parameter Object): अनेक पॅरामीटर्स नैसर्गिकरित्या एकत्र बसत असल्यास त्यांना एका ऑब्जेक्टमध्ये एकत्र करा.
- रिमूव्ह सेटिंग मेथड (Remove Setting Method): जर एखादे फील्ड फक्त सुरूवातीला सेट केले पाहिजे, पण कंस्ट्रक्शननंतर बदलले जाऊ नये, तर सेटर्स टाळा.
- हाइड मेथड (Hide Method): जर एखादी मेथड फक्त एकाच क्लासमध्ये वापरली जात असेल तर तिची व्हिजिबिलिटी कमी करा.
- रिप्लेस कंस्ट्रक्टर विथ फॅक्टरी मेथड (Replace Constructor with Factory Method): कंस्ट्रक्टरसाठी एक अधिक वर्णनात्मक पर्याय.
- रिप्लेस एक्सेप्शन विथ टेस्ट (Replace Exception with Test): जर एक्सेप्शन फ्लो कंट्रोल म्हणून वापरले जात असतील, तर कार्यक्षमता सुधारण्यासाठी त्यांना कंडिशनल लॉजिकने बदला.
जनरलायझेशन हाताळणे
- पुल अप फील्ड (Pull Up Field): एका फील्डला सबक्लासमधून त्याच्या सुपरक्लासमध्ये हलवा.
- पुल अप मेथड (Pull Up Method): एका मेथडला सबक्लासमधून तिच्या सुपरक्लासमध्ये हलवा.
- पुल अप कंस्ट्रक्टर बॉडी (Pull Up Constructor Body): कंस्ट्रक्टरची बॉडी सबक्लासमधून तिच्या सुपरक्लासमध्ये हलवा.
- पुश डाउन मेथड (Push Down Method): एका मेथडला सुपरक्लासमधून तिच्या सबक्लासेसमध्ये हलवा.
- पुश डाउन फील्ड (Push Down Field): एका फील्डला सुपरक्लासमधून तिच्या सबक्लासेसमध्ये हलवा.
- एक्स्ट्रॅक्ट इंटरफेस (Extract Interface): क्लासच्या पब्लिक मेथड्समधून एक इंटरफेस तयार करते.
- एक्स्ट्रॅक्ट सुपरक्लास (Extract Superclass): दोन क्लासेसमधील समान कार्यक्षमता एका नवीन सुपरक्लासमध्ये हलवा.
- कोलॅप्स हायरार्की (Collapse Hierarchy): सुपरक्लास आणि सबक्लासला एकाच क्लासमध्ये एकत्र करा.
- फॉर्म टेम्पलेट मेथड (Form Template Method): सुपरक्लासमध्ये एक टेम्पलेट मेथड तयार करा जी अल्गोरिदमच्या पायऱ्या परिभाषित करते, ज्यामुळे सबक्लासेसना विशिष्ट पायऱ्या ओव्हरराइड करण्याची परवानगी मिळते.
- रिप्लेस इनहेरिटन्स विथ डेलीगेशन (Replace Inheritance with Delegation): क्लासमध्ये कार्यक्षमता इनहेरिट करण्याऐवजी, त्याचा संदर्भ देणारे एक फील्ड तयार करा.
- रिप्लेस डेलीगेशन विथ इनहेरिटन्स (Replace Delegation with Inheritance): जेव्हा डेलीगेशन खूप गुंतागुंतीचे होते, तेव्हा इनहेरिटन्सवर स्विच करा.
ही उपलब्ध असलेल्या अनेक रिफॅक्टरिंग तंत्रांपैकी फक्त काही उदाहरणे आहेत. कोणते तंत्र वापरायचे याची निवड विशिष्ट कोड स्मेल आणि अपेक्षित परिणामावर अवलंबून असते.
उदाहरण: एका जागतिक बँकेद्वारे वापरल्या जाणाऱ्या जावा ऍप्लिकेशनमधील एक मोठी मेथड व्याजदरांची गणना करते. एक्स्ट्रॅक्ट मेथड (Extract Method) वापरून लहान, अधिक केंद्रित मेथड्स तयार केल्याने वाचनीयता सुधारते आणि मेथडच्या इतर भागांवर परिणाम न करता व्याजदर गणना लॉजिक अपडेट करणे सोपे होते.
रिफॅक्टरिंग प्रक्रिया
धोका कमी करण्यासाठी आणि यशाची शक्यता वाढवण्यासाठी रिफॅक्टरिंग पद्धतशीरपणे केले पाहिजे. येथे एक शिफारस केलेली प्रक्रिया आहे:
- रिफॅक्टरिंगसाठी उमेदवार ओळखा: आधी नमूद केलेल्या निकषांचा वापर करून कोडचे असे भाग ओळखा ज्यांना रिफॅक्टरिंगचा सर्वाधिक फायदा होईल.
- टेस्ट्स तयार करा: कोणतेही बदल करण्यापूर्वी, कोडचे विद्यमान वर्तन सत्यापित करण्यासाठी स्वयंचलित (automated) टेस्ट्स लिहा. रिफॅक्टरिंगमुळे नवीन चुका (regressions) होत नाहीत याची खात्री करण्यासाठी हे अत्यंत महत्त्वाचे आहे. JUnit (Java), pytest (Python), किंवा Jest (JavaScript) सारखी साधने युनिट टेस्ट्स लिहिण्यासाठी वापरली जाऊ शकतात.
- टप्प्याटप्प्याने रिफॅक्टर करा: लहान, टप्प्याटप्प्याने बदल करा आणि प्रत्येक बदलानंतर टेस्ट्स चालवा. यामुळे कोणत्याही त्रुटी ओळखणे आणि दुरुस्त करणे सोपे होते.
- वारंवार कमिट करा: तुमचे बदल व्हर्जन कंट्रोलमध्ये वारंवार कमिट करा. यामुळे काही चूक झाल्यास मागील आवृत्तीवर सहज परत जाता येते.
- कोडचे पुनरावलोकन करा: तुमचा कोड दुसऱ्या डेव्हलपरकडून तपासून घ्या. यामुळे संभाव्य समस्या ओळखण्यात आणि रिफॅक्टरिंग योग्यरित्या झाले आहे याची खात्री करण्यास मदत होते.
- कार्यक्षमतेवर लक्ष ठेवा: रिफॅक्टरिंगनंतर, सिस्टीमच्या कार्यक्षमतेवर लक्ष ठेवा जेणेकरून बदलांमुळे कोणतीही कार्यक्षमता कमी झाली नाही याची खात्री होईल.
उदाहरण: एका जागतिक ई-कॉमर्स प्लॅटफॉर्ममधील पायथन मॉड्यूल रिफॅक्टर करणारी एक टीम विद्यमान कार्यक्षमतेसाठी युनिट टेस्ट्स तयार करण्यासाठी `pytest` वापरते. त्यानंतर ते जबाबदाऱ्या वेगळ्या करण्यासाठी आणि मॉड्यूलची रचना सुधारण्यासाठी एक्स्ट्रॅक्ट क्लास (Extract Class) रिफॅक्टरिंग लागू करतात. प्रत्येक लहान बदलानंतर, कार्यक्षमता तशीच राहिली आहे याची खात्री करण्यासाठी ते टेस्ट्स चालवतात.
लेगसी कोडमध्ये टेस्ट्स समाविष्ट करण्यासाठी स्ट्रॅटेजीज
मायकल फेदर्स यांनी योग्यरित्या म्हटल्याप्रमाणे, लेगसी कोड म्हणजे टेस्ट्स नसलेला कोड. विद्यमान कोडबेसमध्ये टेस्ट्स समाविष्ट करणे हे एक मोठे काम वाटू शकते, परंतु सुरक्षित रिफॅक्टरिंगसाठी ते आवश्यक आहे. हे काम करण्यासाठी येथे अनेक स्ट्रॅटेजीज आहेत:
कॅरॅक्टरायझेशन टेस्ट्स (Golden Master Tests)
जेव्हा तुम्ही समजण्यास कठीण असलेल्या कोडशी व्यवहार करत असता, तेव्हा कॅरॅक्टरायझेशन टेस्ट्स तुम्हाला बदल करण्यास सुरुवात करण्यापूर्वी त्याचे विद्यमान वर्तन कॅप्चर करण्यास मदत करू शकतात. कल्पना अशी आहे की दिलेल्या इनपुट सेटसाठी कोडच्या सध्याच्या आउटपुटची तपासणी करणाऱ्या टेस्ट्स लिहा. या टेस्ट्स अचूकतेची पडताळणी करत नाहीत; त्या फक्त कोड *सध्या* काय करतो हे डॉक्युमेंट करतात.
पायऱ्या:
- तुम्ही ज्या कोड युनिटचे कॅरॅक्टरायझेशन करू इच्छिता ते ओळखा (उदा. फंक्शन किंवा मेथड).
- इनपुट व्हॅल्यूजचा एक सेट तयार करा जो सामान्य आणि एज-केस परिस्थितींची श्रेणी दर्शवतो.
- त्या इनपुटसह कोड चालवा आणि परिणामी आउटपुट कॅप्चर करा.
- अशा टेस्ट्स लिहा ज्या हे सिद्ध करतात की कोड त्या इनपुटसाठी तेच अचूक आउटपुट तयार करतो.
सावधानता: जर मूळ लॉजिक गुंतागुंतीचे किंवा डेटा-आधारित असेल तर कॅरॅक्टरायझेशन टेस्ट्स ठिसूळ असू शकतात. तुम्हाला नंतर कोडचे वर्तन बदलण्याची आवश्यकता असल्यास त्या अपडेट करण्यासाठी तयार रहा.
स्प्राउट मेथड आणि स्प्राउट क्लास
मायकल फेदर्स यांनी वर्णन केलेली ही तंत्रे, विद्यमान कोड खराब होण्याचा धोका कमी करून लेगसी सिस्टीममध्ये नवीन कार्यक्षमता समाविष्ट करण्याचा उद्देश ठेवतात.
स्प्राउट मेथड (Sprout Method): जेव्हा तुम्हाला एखादे नवीन फीचर जोडण्याची आवश्यकता असते ज्यासाठी विद्यमान मेथडमध्ये बदल करणे आवश्यक असते, तेव्हा नवीन लॉजिक असलेली एक नवीन मेथड तयार करा. मग, विद्यमान मेथडमधून या नवीन मेथडला कॉल करा. यामुळे तुम्हाला नवीन कोड वेगळा करून स्वतंत्रपणे तपासता येतो.
स्प्राउट क्लास (Sprout Class): स्प्राउट मेथडसारखेच, परंतु क्लासेससाठी. नवीन कार्यक्षमता अंमलात आणणारा एक नवीन क्लास तयार करा आणि नंतर त्याला विद्यमान सिस्टीममध्ये समाकलित करा.
सँडबॉक्सिंग (Sandboxing)
सँडबॉक्सिंगमध्ये लेगसी कोडला सिस्टीमच्या उर्वरित भागापासून वेगळे करणे समाविष्ट आहे, ज्यामुळे तुम्हाला ते नियंत्रित वातावरणात तपासता येते. हे डिपेंडेंसीजसाठी मॉक्स किंवा स्टब्स तयार करून किंवा कोड व्हर्च्युअल मशीनमध्ये चालवून केले जाऊ शकते.
मिकाडो मेथड (The Mikado Method)
मिकाडो मेथड ही गुंतागुंतीच्या रिफॅक्टरिंग कार्यांना हाताळण्यासाठी एक व्हिज्युअल समस्या-निवारण पद्धत आहे. यात कोडच्या वेगवेगळ्या भागांमधील अवलंबित्व दर्शवणारा एक आकृती तयार करणे आणि नंतर सिस्टीमच्या इतर भागांवर कमीत कमी परिणाम होईल अशा प्रकारे कोड रिफॅक्टर करणे समाविष्ट आहे. मूळ तत्व म्हणजे बदल "प्रयत्न" करणे आणि काय बिघडते ते पाहणे. जर ते बिघडले, तर शेवटच्या कार्यरत स्थितीवर परत या आणि समस्येची नोंद करा. मग मूळ बदल पुन्हा प्रयत्न करण्यापूर्वी त्या समस्येचे निराकरण करा.
रिफॅक्टरिंगसाठी साधने (टूल्स)
अनेक साधने रिफॅक्टरिंगमध्ये मदत करू शकतात, पुनरावृत्ती होणारी कामे स्वयंचलित करतात आणि सर्वोत्तम पद्धतींवर मार्गदर्शन करतात. ही साधने अनेकदा इंटिग्रेटेड डेव्हलपमेंट एन्व्हायर्नमेंट्स (IDEs) मध्ये समाकलित केलेली असतात:
- आयडीई (IDEs) (उदा., IntelliJ IDEA, Eclipse, Visual Studio): आयडीई अंगभूत रिफॅक्टरिंग साधने प्रदान करतात जी व्हेरिएबल्सचे नाव बदलणे, मेथड्स काढणे आणि क्लासेस हलवणे यासारखी कामे स्वयंचलितपणे करू शकतात.
- स्टॅटिक ॲनालिसिस टूल्स (उदा., SonarQube, Checkstyle, PMD): ही साधने कोड स्मेल्स, संभाव्य बग्स आणि सुरक्षा भेद्यतांसाठी कोडचे विश्लेषण करतात. ते कोडचे असे क्षेत्र ओळखण्यास मदत करू शकतात ज्यांना रिफॅक्टरिंगचा फायदा होईल.
- कोड कव्हरेज टूल्स (उदा., JaCoCo, Cobertura): ही साधने टेस्ट्सद्वारे किती टक्के कोड कव्हर केला आहे हे मोजतात. ते कोडचे असे क्षेत्र ओळखण्यास मदत करू शकतात जे पुरेशा प्रमाणात तपासलेले नाहीत.
- रिफॅक्टरिंग ब्राउझर्स (उदा., Smalltalk Refactoring Browser): मोठ्या पुनर्रचना कार्यांमध्ये मदत करणारी विशेष साधने.
उदाहरण: एका जागतिक विमा कंपनीसाठी C# ऍप्लिकेशनवर काम करणारी एक डेव्हलपमेंट टीम व्हेरिएबल्सचे नाव बदलण्यासाठी आणि मेथड्स काढण्यासाठी Visual Studio च्या अंगभूत रिफॅक्टरिंग साधनांचा वापर करते. ते कोड स्मेल्स आणि संभाव्य भेद्यता ओळखण्यासाठी SonarQube चा देखील वापर करतात.
आव्हाने आणि धोके
लेगसी कोड रिफॅक्टर करणे आव्हाने आणि धोक्यांशिवाय नाही:
- रिग्रेशन्स (Bugs) निर्माण होणे: सर्वात मोठा धोका म्हणजे रिफॅक्टरिंग प्रक्रियेदरम्यान बग्स निर्माण होणे. सर्वसमावेशक टेस्ट्स लिहून आणि टप्प्याटप्प्याने रिफॅक्टरिंग करून हे कमी केले जाऊ शकते.
- डोमेन ज्ञानाचा अभाव: जर मूळ डेव्हलपर्स पुढे गेले असतील, तर कोड आणि त्याचा उद्देश समजणे कठीण होऊ शकते. यामुळे चुकीचे रिफॅक्टरिंग निर्णय घेतले जाऊ शकतात.
- टाइट कपलिंग (Tight Coupling): घट्टपणे जोडलेला कोड रिफॅक्टर करणे अधिक कठीण असते, कारण कोडच्या एका भागातील बदलांचे कोडच्या इतर भागांवर अनपेक्षित परिणाम होऊ शकतात.
- वेळेची मर्यादा: रिफॅक्टरिंगला वेळ लागू शकतो, आणि नवीन फीचर्स देण्यावर लक्ष केंद्रित असलेल्या भागधारकांना गुंतवणुकीचे समर्थन करणे कठीण होऊ शकते.
- बदलाला विरोध: काही डेव्हलपर्स रिफॅक्टरिंगला विरोध करू शकतात, विशेषतः जर ते या तंत्रांशी परिचित नसतील.
सर्वोत्तम पद्धती (Best Practices)
लेगसी कोड रिफॅक्टरिंगशी संबंधित आव्हाने आणि धोके कमी करण्यासाठी, या सर्वोत्तम पद्धतींचे अनुसरण करा:
- सर्वांची संमती मिळवा: भागधारकांना रिफॅक्टरिंगचे फायदे समजले आहेत आणि ते आवश्यक वेळ आणि संसाधने गुंतवण्यास तयार आहेत याची खात्री करा.
- लहान सुरुवात करा: कोडच्या लहान, वेगळ्या तुकड्यांना रिफॅक्टर करून सुरुवात करा. यामुळे आत्मविश्वास वाढण्यास आणि रिफॅक्टरिंगचे मूल्य प्रदर्शित करण्यास मदत होईल.
- टप्प्याटप्प्याने रिफॅक्टर करा: लहान, टप्प्याटप्प्याने बदल करा आणि वारंवार टेस्ट करा. यामुळे कोणत्याही त्रुटी ओळखणे आणि दुरुस्त करणे सोपे होईल.
- टेस्ट्स ऑटोमेट करा: रिफॅक्टरिंगपूर्वी आणि नंतर कोडचे वर्तन सत्यापित करण्यासाठी सर्वसमावेशक स्वयंचलित टेस्ट्स लिहा.
- रिफॅक्टरिंग टूल्सचा वापर करा: पुनरावृत्ती होणारी कामे स्वयंचलित करण्यासाठी आणि सर्वोत्तम पद्धतींवर मार्गदर्शन मिळवण्यासाठी तुमच्या आयडीई किंवा इतर साधनांमधील रिफॅक्टरिंग टूल्सचा लाभ घ्या.
- तुमच्या बदलांची नोंद ठेवा: रिफॅक्टरिंग दरम्यान तुम्ही केलेल्या बदलांची नोंद ठेवा. यामुळे इतर डेव्हलपर्सना कोड समजण्यास आणि भविष्यात रिग्रेशन्स टाळण्यास मदत होईल.
- सतत रिफॅक्टरिंग: रिफॅक्टरिंगला एक-वेळची घटना न बनवता विकास प्रक्रियेचा एक सततचा भाग बनवा. यामुळे कोडबेस स्वच्छ आणि देखभाल करण्यायोग्य ठेवण्यास मदत होईल.
निष्कर्ष
लेगसी कोड रिफॅक्टर करणे हे एक आव्हानात्मक परंतु फायद्याचे काम आहे. या मार्गदर्शिकेत दिलेल्या स्ट्रॅटेजीज आणि सर्वोत्तम पद्धतींचे पालन करून, तुम्ही या अवघड कामावर मात करू शकता आणि तुमच्या लेगसी सिस्टीम्सना देखभाल करण्यायोग्य, विश्वसनीय आणि उच्च-कार्यक्षमता असलेल्या मालमत्तेत बदलू शकता. रिफॅक्टरिंग पद्धतशीरपणे हाताळा, वारंवार टेस्ट करा आणि तुमच्या टीमशी प्रभावीपणे संवाद साधा. काळजीपूर्वक नियोजन आणि अंमलबजावणी करून, तुम्ही तुमच्या लेगसी कोडमधील सुप्त क्षमता अनलॉक करू शकता आणि भविष्यातील नवनिर्मितीचा मार्ग मोकळा करू शकता.