لماذا تفلت أخطاء الكود في Windsurf من المراجعة
تتناسب المراجعة البشرية مع عدد الأسطر التي يستطيع المرء الاحتفاظ بها في ذهنه، والتغيير الواسع الميكانيكي يُبطلها بطريقة محددة: كل مقطع من الفروق يبدو معقولًا بمفرده، فيتراخى الانتباه. تعتمد الملف الثاني عشر بتدقيق أقل مما منحته للأول، والعيب يكون في الذيل دائمًا تقريبًا.
والعيب نادرًا ما يكون فيما تغيّر، بل فيما لم يتغيّر: إعادة تسمية أغفلت موضع استدعاء واحدًا، أو حقل مطلوب جديد لا تمرّره ثلاثة مُنشئات، أو معالج جرى تحديثه في كل مكان عدا مسار الخطأ.
الأشكال الثلاثة التي ينكسر فيها التغيير الواسع
تمشيط ناقص
أحد عشر موضع استدعاء جرى تحديثها، وواحد فات، وهو على مسار لا يسلكه أحد يوميًا.
وكثيرًا ما تعجز الأنواع عن اكتشافه لأن الموضع الذي فات كان أصلًا ضعيف التحديد النوعي.
انحراف الافتراضات
ينتهي الأمر بملفين يختلفان حول معنى قيمة ما، مثل ما إذا كان الطابع الزمني بالثواني أم بالميلي ثانية.
كل ملف متسق داخليًا، فلا يبدو شيء خاطئًا عند النظر إليه بمعزل عن الآخر.
تغيّر صامت في السلوك
إعادة هيكلة تحافظ على الواجهة وتغيّر في صمت الترتيب أو القيم الافتراضية أو مسار الخطأ.
والاختبارات المكتوبة على أساس التنفيذ القديم تظل تنجح لأنها تتحقق من الواجهة.
وتشترك الأشكال الثلاثة في خاصية واحدة: تجدها باستخدام التطبيق لا بقراءته. وهذا ما يجعل كلفتها باهظة.
تحقّق من السلوك لا من الفروق
في التغيير الواسع، السؤال المفيد ليس «هل كل تعديل صحيح؟» بل «هل ما زال المنتج يفعل ما كان يفعله، مضافًا إليه الشيء الجديد؟». هذا سؤال سلوكي، وإجابته تأتي من تشغيل التطبيق المنشور عبر المسارات التي يُرجَّح أن التغيير قد مسّها.
ولا يلزم أن تكون التغطية شاملة لتكون مفيدة. فالتغيير الذي يعيد تسمية حقل عبر مسار إتمام الشراء يحتاج إلى تنفيذ ذلك المسار من طرف إلى طرف مرة واحدة، وهذا أثمن من قراءة فروق اثني عشر ملفًا بعناية.
ثبّت مهارة التحقق داخل المحرّر ليتمكن الوكيل من إجراء هذا الفحص بنفسه بدل انتظارك.
الطرفية
npm install -g @testsprite/testsprite-cli
testsprite setup
وتقوم لوحة التحكم بالإعداد نفسه إن كنت تفضّل ألا تثبّت شيئًا. أما بقية إمكانات الـ CLI فتجدها في مستودع CLI.
أعطِ الوكيل الخلل نفسه، لا ملخّصك عنه
وحين ينكسر شيء فعلًا، لا تُغلق حلقة الإصلاح إلا إذا كانت الأدلة قابلة للاستخدام: ما الذي جرت محاولته، وما الذي فعله التطبيق، وأين افترقا. فإذا سُلّم الوكيل ذلك، عاد إلى الملفات الاثني عشر نفسها ومعه هدف محدد. أما إذا سُلّم لقطة شاشة، فسيخمّن، وتعود أنت إلى وصف الأمور.
قراءة الفروق الواسعة دون تظاهر
ثمة طريقة صادقة لمراجعة تغيير يشمل اثني عشر ملفًا، وهي ليست قراءة كل مقطع، بل أن تحدّد قبل أن تفتح الفروق ما الذي يجب أن يكون صحيحًا حتى يكون هذا التغيير صحيحًا، ثم تفحص تلك الأمور وحدها.
ففي إعادة التسمية، السؤال هو هل انتقلت كل مواضع الاستدعاء، وهذا يجيب عنه المُصرِّف في معظمه، وهل يبني شيء ما الاسم ديناميكيًا، وهذا لا يجيب عنه. وفي الحقل المطلوب الجديد، السؤال هو كل مسار يبني الكائن، بما في ذلك الاختبارات وبيانات التهيئة التي ستظل تمرّر نسخة ناقصة في صمت. وفي إعادة الهيكلة التي تحافظ على الواجهة، السؤال هو الترتيب ومسارات الخطأ، لأنها ما تغيّره إعادة الهيكلة بهدوء.
ثلاثة أسئلة عن كل تغيير أفضل من تصفّح أربعمئة سطر، وهي تتركك بقائمة صادقة بما لا يزال يتعين التحقق منه عبر تشغيل المنتج فعليًا.
اختر المسارات بحسب نطاق الأثر لا بحسب الأهمية
يميل الناس بالفطرة إلى تغطية أهم ميزة. لكن في التغيير الواسع، السؤال الأفضل هو: أي المسارات يُرجَّح أن التغيير قد مسّها، مرتّبةً بحسب مدى صمت انهيارها.
مسار الدفع مهم، وهو أيضًا مُراقَب؛ فإن انكسر عرفت بذلك خلال ساعة. أما الخطِرة فهي المسارات التي تهمّ لكنها تُستخدم أسبوعيًا لا كل ساعة: تصدير، أو دعوة، أو صفحة إعدادات، أو ملخّص مجدول. هناك يرقد التمشيط الناقص دون أن يزعجه أحد شهرًا كاملًا.
لذا، بعد أي تغيير واسع، جرّب المسارات الهادئة أولًا؛ فتغطيتها رخيصة، وهي التي لا يفحصها أحد غيرك.
شغّله مع كل طلب سحب
التغييرات الواسعة هي بالضبط ما يميل الناس إلى دمجه سريعًا لأن فروقه مملّة. وهذه هي الحجة على جعل الفحص تلقائيًا بدل الاعتماد على التذكّر.
طريقان، والاختيار بينهما يتعلق في حقيقته بمن يملك خط الإنتاج. فربط GitHub App من لوحة التحكم لا يستلزم أي تغيير في مستودعك على الإطلاق، لأنه يتفاعل مع عملية النشر التي يُصدرها بناؤك أصلًا. أما إضافة خطوة GitHub Actions فتضع الفحص داخل المستودع حيث يُراجَع كسائر مراحل البناء.
التحقق من تغيير واسع دون قراءته
يجيب TestSprite عن السؤال الذي تعجز الفروق الواسعة عن الإجابة عنه: هل ما زال المنتج يفعل ما كان يفعله، مضافًا إليه الشيء الجديد؟ فهو يفتح التطبيق المنشور، ويمرّ عبر المسارات التي يُرجَّح أن التغيير قد مسّها، ويُبلّغ عن السلوك لا عن البنية.
وهذا هو الشكل الصحيح لهذه المشكلة، فالتمشيط الناقص وانحراف الافتراضات وتغيّرات السلوك الصامتة كلها غير مرئية في الشيفرة وبديهية عند الاستخدام. والتغطية تُولَّد من منتجك بدل أن تُكتب يدويًا، فتدخل فيها المسارات الهادئة، من تصدير ودعوة وصفحة إعدادات، دون أن يتذكّرها أحد.
وحين ينكسر شيء فعلًا، يعود الخلل في حزمة واحدة يستطيع وكيلك التصرّف بناءً عليها، وهذا هو الأهم هنا: توجيهه إلى موضع الاختلاف المحدد أجدى من مطالبته بإعادة فحص اثني عشر ملفًا.
لماذا لا تكتشف الأنواع هذه الأخطاء؟
إنها تكتشف نصيبًا وافرًا من التمشيط الناقص، ولا تكاد تكتشف شيئًا من انحراف الافتراضات أو تغيّرات السلوك الصامتة، لأن كليهما سليم نوعيًا بحكم تكوينه.
هل يكفي أن أطلب تغييرات أصغر؟
هذا يساعد، لكنه يفرّط في معظم سبب استخدام محرّر وكيل أصلًا. أما خطوة التحقق فتتيح لك الإبقاء على الاتساع مع معرفة ما إذا كانت النتيجة تعمل.
هل ينطبق هذا حين يكون التغيير في الواجهة الخلفية فقط؟
نعم، عبر التغطية على مستوى API بدل الواجهة. والمبدأ نفسه: شغّل السلوك بدل قراءة التغيير.
كم يستغرق فحص كهذا؟
طويل بما يكفي لئلا تشغّله مع كل ضغطة مفتاح، وقصير بما يكفي ليُدرَج في طلب سحب. وهذا هو موضعه الصحيح.
ماذا لو كان الوكيل قد شغّل اختبارات الوحدة بالفعل؟
مفيد، لكن اختبارات الوحدة تُكتب عادةً بناءً على الافتراضات نفسها التي غيّرها التغيير للتو، فهي تؤكد الاتساق الداخلي لا الصحة الخارجية.
عند اثني عشر ملفًا، قراءة الفروق ليست فحصًا.
تختبئ أخطاء الكود في Windsurf في التمشيط الناقص وانحراف الافتراضات وتغيّرات السلوك الصامتة. تحقّق من المنتج وهو يعمل بدل التحقق من الفروق، وأعِد الأخطاء إلى الوكيل بوصفها أدلة، واجعل الفحص يعمل مع كل طلب سحب.