لماذا يُعد الكود الخالي من الأخطاء هدفًا خاطئًا

في كل نظام عيوب لم يصطدم بها أحد بعد، وتكلفة العثور على العيب التالي ترتفع بحدّة كلما أُزيلت العيوب الظاهرة. وبعد حدٍّ معيّن، تصبح الساعة الإضافية المنفقة في مطاردة العيوب أقل قيمة من الساعة نفسها لو أُنفقت في جعل الأعطال رخيصة الاكتشاف والإصلاح.

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

ثلاثة أهداف مُجدية

لا تكرار

  • الخطأ الواحد يقع مرة واحدة. وكل إصلاح يترك خلفه فحصًا.

  • قابل للتحقيق، وأثره يتراكم.

الاكتشاف قبل المستخدمين

  • انقل الاكتشاف من الإنتاج إلى طلب السحب.

  • قابل للقياس: ما نسبة ما التُقط داخليًا.

رخيص الإصلاح

  • الزمن من العطل إلى الإصلاح، وهو يعتمد في معظمه على جودة تقرير العطل.

لماذا الهدف الأول هو الأهم

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

القياس

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

لماذا تواصل الفرق مطاردته رغم ذلك

معرفة أن الهدف خاطئ لا تمنع الناس من التصويب نحوه، والسبب يستحق الفهم لأنه بنيوي لا ساذج.

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

والعلاج هو جعل الوقاية مرئية أيضًا. أعلِن عدد العيوب التي التُقطت قبل الإصدار إلى جانب عدد ما أفلت منها. الرقم الأول أكبر بكثير عادةً، ورؤيته تنقل الحديث من «لماذا تتكرر الأخطاء لدينا» إلى «هل النسبة تتحسّن»، وهذا هو السؤال الذي له إجابة مفيدة.

كيف يبدو هذا عمليًا

كل خطأ يحصل على فحص. والفحوص تعمل مع كل تغيير لا قبل الإصدارات. وتصل الأعطال في صورة يستطيع المُصلِح التصرّف بناءً عليها دون إعادة استنتاج القصة.

الطرفية

npm install -g @testsprite/testsprite-cli
testsprite setup

ولوحة التحكم تغطي المجال نفسه لمن لا يريد تثبيتًا محليًا، أما مجموعة الأوامر الكاملة فتوجد في مستودع CLI.

المُشغِّل أهم من الآلية. فتوجيهه إلى حدث النشر لديك يعني أن كل تغيير يُفحص دون أن يقرر ذلك أحد؛ ويقوم GitHub App بذلك من لوحة التحكم، بينما تفعله خطوة GitHub Actions من داخل سير عملك.

كيف تدعم TestSprite الأهداف الثلاثة

«لا تكرار» هو الهدف الذي تخدمه بشكل مباشر أكثر من غيره. فالحالة التي أعادت إنتاج الخطأ تبقى في المشروع وتعمل مع كل تغيير، فيترك الإصلاح خلفه فحصًا دون أن يتذكر أحد كتابته.

و«الاكتشاف قبل المستخدمين» مسألة إيقاع. فالتغطية تُولَّد من منتجك وتعمل على طلب السحب، ما ينقل الاكتشاف من الإنتاج إلى التغيير الذي تسبّب فيه.

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

هل يمكن بلوغ الخلوّ من الأخطاء يومًا؟

في الأنظمة الصغيرة ذات المواصفات الشكلية الرسمية، يقترب الأمر من ذلك، لكن بتكلفة لا يكاد أحد يستطيع تبريرها. أما في منتج عادي، فلا.

ما معدل العيوب المعقول؟

قارِن باتجاهك أنت لا برقم قطاعي. الاتجاه أهم من المستوى.

هل يعني مزيد من الاختبار أخطاءً أقل؟

إلى حدٍّ معيّن. وبعده تضيف الاختبارات الإضافية صيانة دون أن تضيف إشارة، خصوصًا إن كررت ما تغطّيه بالفعل.

هل ينبغي تتبّع أعداد الأخطاء؟

تابِع العيوب المفلتة وزمن الإصلاح. أما الأعداد الخام فترتفع كلما تحسّن الإبلاغ، ما يجعلها إشارة رديئة.

ما العادة الأعلى أثرًا على الإطلاق؟

اترك خلفك فحصًا في كل مرة تُصلح فيها شيئًا. إنها العادة الوحيدة التي يتراكم أثرها.

الخلاصة

استهدف ألّا يتكرر الخطأ، لا أن يبلغ العدد صفرًا.

الكود الخالي من الأخطاء غير قابل للتحقيق ويشوّه الأولويات. استهدف: لا تكرار، والاكتشاف قبل المستخدمين، والإصلاح الرخيص. اترك خلفك فحصًا بعد كل إصلاح، وقِس العيوب المفلتة بدل أعداد الاختبارات.