اختبار A/B في C#: كيف تتوقف عن التخمين وتبدأ في جني الأرباح

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا يعمل كود C# الخاص بك دون جدوى (وكيفية إصلاح ذلك)

\n\n

لقد أمضيت أسابيع في إعادة هيكلة خوارزمية التوصيات. الإصدار الجديد من RecommendationService يبدو لا تشوبه شائبة، الكود أنظف، استعلامات LINQ أسرع. تقوم بنشر التحديث إلى الإنتاج، و... ينخفض معدل التحويل بنسبة 15%. هل يبدو هذا مألوفًا؟ إذا لم يكن كذلك، فأنت محظوظ. إذا كان كذلك، فقد فقدت المال والوقت للتو لأنك اعتمدت على الحدس، وليس على البيانات.

\n\n

في عالم تطوير C#، هناك قاعدة ذهبية: "لا تثق أبدًا برأيك، ثق بالإحصائيات". ولهذا السبب تحديدًا يوجد اختبار A/B (أو اختبار الانقسام). إنها ليست حيلة تسويقية - بل هي نهج هندسي لاتخاذ القرارات. في هذه المقالة، سنشرح كيفية تطبيق اختبار A/B كامل في تطبيق C# الخاص بك: من البنية التحتية إلى حساب الدلالة الإحصائية. ونعم، سيكون هناك الكثير من الكود.

\n\n

ما هو اختبار A/B في سياق C#؟

\n\n

تخيل أن لديك نسختين من نفس المنطق - المجموعة الضابطة A (النسخة القديمة) والمجموعة التجريبية B (النسخة الجديدة). تقوم بتوزيع المستخدمين عشوائيًا بينهما، وتجمع المقاييس، وباستخدام الرياضيات تحدد أي نسخة هي الأفضل حقًا.

\n\n

في C#، يمكن أن يتعلق هذا بأي شيء:

\n
    \n
  • تغيير خوارزمية البحث
  • \n
  • تصميم جديد لنموذج الدفع
  • \n
  • خيارات مختلفة لترتيب المنتجات
  • \n
  • تجارب مع وقت التخزين المؤقت
  • \n
  • اختبار نماذج التعلم الآلي
  • \n
\n\n

النقطة الأساسية: اختبار A/B في C# لا يتعلق بـ "وضع علامة في ملف التكوين". إنه يتعلق بـ بنية نظيفة، العشوائية، وجمع المقاييس بدون أخطاء.

\n\n

بنية اختبار A/B: طبقات الكيك في C#

\n\n

دعنا ننتقل مباشرة إلى التطبيق العملي. سأعرض لك بنية بسيطة ولكنها عملية. تتكون من ثلاث طبقات:

\n\n
    \n
  1. المُعيّن (Assigner) - يقرر المجموعة التي ينتمي إليها المستخدم.
  2. \n
  3. قرار الميزة (Feature Decision) - أي نسخة من الكود سيتم تنفيذها.
  4. \n
  5. المُتعقّب (Tracker) - يسجل الحدث والنتيجة.
  6. \n
\n\n

الخطوة 1: المُعيّن - من أنت أيها المستخدم؟

\n\n

الخطأ الأكثر شيوعًا هو العشوائية غير الصحيحة. استخدام Random فكرة سيئة، لأنه عند إعادة تشغيل التطبيق، ستتغير المجموعات. الحل الصحيح هو التوزيع الحتمي بناءً على معرف المستخدم.

\n\n
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: قرار الميزة - معركة الخوارزميات

\n\n

الآن نحتاج إلى أن يختار الكود تلقائيًا أي منطق سيتم تنفيذه. نستخدم نمط الإستراتيجية مع المصنع.

\n\n
public 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                

المدونات

توصيات الكتب