आपका C# कोड बेकार क्यों काम कर रहा है (और इसे कैसे ठीक करें)
\n\nआपने अनुशंसा एल्गोरिदम के रीफैक्टरिंग पर सप्ताह बिताए। RecommendationService का नया संस्करण दोषरहित दिखता है, कोड साफ है, LINQ क्वेरी तेज़ हैं। आप प्रोडक्शन पर अपडेट जारी करते हैं, और… रूपांतरण 15% गिर जाता है। परिचित लगता है? यदि नहीं — तो आप भाग्यशाली हैं। यदि हाँ — तो आपने अभी पैसा और समय खो दिया है, क्योंकि आपने अपने अंतर्ज्ञान पर भरोसा किया, डेटा पर नहीं।
C# डेवलपमेंट की दुनिया में एक सुनहरा नियम है: "अपनी राय पर कभी भरोसा न करें, आँकड़ों पर भरोसा करें"। यही कारण है कि A/B परीक्षण (या स्प्लिट-परीक्षण) मौजूद है। यह कोई मार्केटिंग चाल नहीं है — यह निर्णय लेने का एक इंजीनियरिंग दृष्टिकोण है। इस लेख में, हम आपके C# एप्लिकेशन में पूर्ण A/B परीक्षण लागू करने का तरीका समझेंगे: आर्किटेक्चर से लेकर सांख्यिकीय महत्व की गणना तक। और हाँ, बहुत सारा कोड होगा।
\n\nC# के संदर्भ में A/B परीक्षण क्या है?
\n\nकल्पना करें कि आपके पास एक ही तर्क के दो संस्करण हैं — नियंत्रण समूह A (पुराना संस्करण) और प्रयोगात्मक समूह B (नया संस्करण)। आप यादृच्छिक रूप से उपयोगकर्ताओं को उनके बीच वितरित करते हैं, मीट्रिक एकत्र करते हैं और गणित की मदद से निर्धारित करते हैं कि कौन सा संस्करण वास्तव में बेहतर है।
\n\nC# में, यह किसी भी चीज़ से संबंधित हो सकता है:
\n- \n
- खोज एल्गोरिदम में बदलाव \n
- भुगतान फॉर्म का नया डिज़ाइन \n
- उत्पाद सॉर्टिंग के विभिन्न विकल्प \n
- कैशिंग समय के साथ प्रयोग \n
- ML मॉडल का परीक्षण \n
मुख्य बिंदु: C# में A/B परीक्षण "कॉन्फ़िग में फ़्लैग सेट करना" नहीं है। यह स्वच्छ आर्किटेक्चर, यादृच्छिकीकरण और बग-मुक्त मीट्रिक संग्रह के बारे में है।
\n\nA/B परीक्षण आर्किटेक्चर: C# पर लेयर केक
\n\nआइए सीधे अभ्यास पर आते हैं। मैं आपको एक न्यूनतम लेकिन कार्यशील आर्किटेक्चर दिखाऊंगा। इसमें तीन परतें होती हैं:
\n\n- \n
- Assigner — यह तय करता है कि उपयोगकर्ता किस समूह में आता है। \n
- Feature Decision — कोड का कौन सा संस्करण निष्पादित करना है। \n
- Tracker — घटना और परिणाम रिकॉर्ड करता है। \n
चरण 1: Assigner — तुम कौन हो, उपयोगकर्ता?
\n\nसबसे आम बग गलत यादृच्छिकीकरण है। Random का उपयोग करना एक बुरा विचार है, क्योंकि एप्लिकेशन को पुनरारंभ करने पर समूह "बह" जाएंगे। सही समाधान UserId पर आधारित नियतात्मक वितरण है।
public interface IExperimentAssigner\n{\n string GetVariant(string userId, string experimentName);\n}\n\npublic class ConsistentExperimentAssigner : IExperimentAssigner\n{\n public string GetVariant(string userId, string experimentName)\n {\n // userId + experimentName से एक स्थिर हैश बनाएँ\n var hash = HashCode.Combine(userId, experimentName);\n // मॉड्यूल 100 लें — प्रतिशत प्राप्त करें\n var bucket = Math.Abs(hash) % 100;\n \n // मान लें, 50% A में, 50% B में\n return bucket < 50 ? "A" : "B";\n }\n}\n\n\nअब एक ही उपयोगकर्ता किसी विशिष्ट प्रयोग के लिए हमेशा एक ही समूह में रहेगा। डेटा की सटीकता के लिए यह महत्वपूर्ण है।
\n\nचरण 2: Feature Decision — एल्गोरिदम की लड़ाई
\n\nअब हमें चाहिए कि कोड स्वयं चुने कि कौन सा तर्क निष्पादित करना है। हम फ़ैक्टरी के साथ स्ट्रैटेजी पैटर्न का उपयोग करते हैं।
\n\npublic interface IPricingStrategy\n{\n decimal CalculatePrice(decimal basePrice);\n}\n\npublic class OldPricingStrategy : IPricingStrategy\n{\n public decimal CalculatePrice(decimal basePrice) \n => basePrice; // बिना छूट के\n}\n\npublic class NewPricingStrategy : IPricingStrategy\n{\n public decimal CalculatePrice(decimal basePrice) \n => basePrice * 0.9m; // 10% छूट\n}\n\npublic class PricingStrategyFactory\n{\n private readonly IExperimentAssigner _assigner;\n\n public PricingStrategyFactory(IExperimentAssigner assi