Go Legacy कोड रिफैक्टरिंग: A से Z तक पूर्ण गाइड

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

परिचय: Go में Legacy कोड को रिफैक्टर क्यों करें?

\n

Go (Golang) अपनी सादगी, प्रदर्शन और समानांतरता (concurrency) के लिए जाना जाता है। लेकिन समय के साथ किसी भी प्रोजेक्ट में "तकनीकी कर्ज" जमा हो जाता है: ग्लोबल वेरिएबल, इंटरफेस की कमी, मैजिक नंबर, अपठनीय फंक्शन और टेस्ट की अनुपस्थिति। ऐसे कोड को legacy कहते हैं। रिफैक्टरिंग का मतलब सब कुछ नए सिरे से लिखना नहीं है, बल्कि बाहरी व्यवहार को बदले बिना संरचना में धीरे-धीरे सुधार करना है। इस लेख में हम Go legacy कोड के रिफैक्टरिंग का चरण-दर-चरण प्लान समझेंगे, विश्लेषण से लेकर कार्यान्वयन तक।

\n\n

चरण 1: Legacy कोड का निदान

\n

कुछ भी बदलने से पहले, यह समझना ज़रूरी है कि हम किसके साथ काम कर रहे हैं। Go प्रोजेक्ट्स में मुख्य "लाल झंडे" ये हैं:

\n
    \n
  • ग्लोबल वेरिएबल (var db *sql.DB) — टेस्टिंग और समानांतर काम को मुश्किल बनाते हैं।
  • \n
  • राक्षसी फंक्शन (50-100 लाइनों से अधिक) — कोड को अपठनीय बनाते हैं।
  • \n
  • इंटरफेस की कमी — विशिष्ट कार्यान्वयन से कठोर जुड़ाव।
  • \n
  • मैजिक स्ट्रिंग/नंबर — खोज और बदलाव को कठिन बनाते हैं।
  • \n
  • टेस्ट की कमी — बिना टेस्ट के रिफैक्टरिंग पतली बर्फ पर चलने जैसा है।
  • \n
\n

विश्लेषण के लिए उपकरण: संदिग्ध संरचनाओं को खोजने के लिए go vet और staticcheck का उपयोग करें। साइक्लोमैटिक जटिलता की गणना के लिए gocyclo भी उपयोगी है।

\n

समस्याग्रस्त कोड का उदाहरण:

\n
package main\n\nimport "fmt"\n\nvar config map[string]string // ग्लोबल वेरिएबल\n\nfunc main() {\n    config = map[string]string{"port": "8080"}\n    startServer()\n}\n\nfunc startServer() {\n    // मैजिक स्ट्रिंग "port"\n    fmt.Println("Starting on port:", config["port"])\n    // ... 100 लाइनें कोड\n}
\n\n

चरण 2: टेस्ट से सुरक्षा जाल बनाना

\n

टेस्ट के बिना रिफैक्टरिंग अंदाज़ा लगाने जैसा है। आपका काम है बदलावों से पहले मुख्य लॉजिक को टेस्ट से कवर करना। जटिल आउटपुट या इंटीग्रेशन टेस्ट के लिए Golden Files (संदर्भ फ़ाइलें) दृष्टिकोण का उपयोग करें।

\n

Legacy कोड में फंक्शन के लिए टेस्ट जोड़ने का उदाहरण:

\n
// legacy.go (मूल)\nfunc CalculateDiscount(price float64, isPremium bool) float64 {\n    if isPremium {\n        return price * 0.9\n    }\n    return price * 0.95\n}\n\n// legacy_test.go\npackage main\n\nimport "testing"\n\nfunc TestCalculateDiscount_Premium(t *testing.T) {\n    result := CalculateDiscount(100.0, true)\n    expected := 90.0\n    if result != expected {\n        t.Errorf("Expected %f, got %f", expected, result)\n    }\n}\n\nfunc TestCalculateDiscount_Regular(t *testing.T) {\n    result := CalculateDiscount(100.0, false)\n    expected := 95.0\n    if result != expected {\n        t.Errorf("Expected %f, got %f", expected, result)\n    }\n}
\n

सुझाव: कवरेज का आकलन करने के लिए go test -cover का उपयोग करें। रिफैक्टरिंग शुरू करने से पहले कम से कम 70% बिज़नेस लॉजिक को कवर करने का प्रयास करें।

\n\n

चरण 3: धीरे-धीरे डीकंपोज़िशन और इंटरफेस का निर्माण

\n

रिफैक्टरिंग का मुख्य उद्देश्य कोड को टेस्ट करने योग्य और लचीला बनाना है। बाहरी निर्भरताओं (डेटाबेस, HTTP क्लाइंट, फ़ाइल सिस्टम) के लिए इंटरफेस बनाकर शुरू करें।

\n

3.1 सीधे DB उपयोग के बजाय इंटरफेस बनाना

\n

मान लीजिए, हमारे पास एक फंक्शन है जो सीधे *sql.DB के साथ काम करता है:

\n
// legacy code\nfunc GetUser(db *sql.DB, id int) (*User, error) {\n    row := db.QueryRow("SELECT id, name FROM users WHERE id = ?", id)\n    // ...\n}
\n

रिफैक्टरिंग: UserRepository इंटरफेस बनाएं:

\n
type UserRepository interface {\n    GetByID(id int) (*User, error)\n}\n\ntype userRepo struct {\n    db *sql.DB\n}\n\nfunc (r *userRepo) GetByID(id int) (*User, error) {\n    row := r.db.QueryRow("SELECT id, name FROM users WHERE id = ?", id)\n

ब्लॉग

पुस्तक अनुशंसाएँ