Skip to content

فن التصحيح (Debugging)

مقدمة

انتهيت من كتابة الكود، شغلته وظهر خطأ — ماذا الآن؟ كثير من المبتدئين يتوقفون عند هذه النقطة، يحدقون في الشاشة بلا حيلة. التصحيح (Debug) هو أحد أهم المهارات الأساسية في البرمجة، بل أهم من كتابة الكود نفسه. لأن كتابة الكود تشغل 30% فقط من وقت التطوير، والـ 70% المتبقية تُقضى في فهم المشكلة وتحديد الأخطاء والتحقق من الإصلاح.

ماذا ستتعلم في هذا المقال؟

بعد إتمام هذا الفصل، ستكتسب:

  • عقلية التصحيح: بناء طريقة منهجية لتحديد المشاكل، بدلاً من "التخمين"
  • قدرة قراءة الأخطاء: فهم رسائل الخطأ وتحديد المشكلة بسرعة من تتبع الاستدعاءات
  • أساليب التصحيح الكلاسيكية: إتقان التقسيم الثنائي، البط المطاطي، إعادة الإنتاج الأدنى وغيرها
  • مهارة استخدام الأدوات: التعرف على سيناريوهات استخدام نقاط التوقف، سجلات التنفيذ، وتصحيح الشبكة
  • التصحيح بمساعدة الذكاء الاصطناعي: تعلم استخدام الذكاء الاصطناعي لتسريع التصحيح دون الاعتماد عليه
الفصلالمحتوىالمفهوم الأساسي
الفصل 1قراءة رسائل الخطأأنواع الأخطاء، تتبع الاستدعاءات
الفصل 2أساليب التصحيح الكلاسيكيةالتقسيم الثنائي، البط المطاطي، إعادة الإنتاج الأدنى
الفصل 3صندوق أدوات التصحيحنقاط التوقف، السجلات، التقاط الشبكة
الفصل 4التصحيح في عصر الذكاء الاصطناعيمساعدة الذكاء الاصطناعي + الحكم البشري
الفصل 5عقلية وعادات التصحيحالبرمجة الدفاعية، سجلات التصحيح

0. نظرة عامة: التصحيح منهج علمي

التصحيح ليس "حظاً"، بل عملية علمية دقيقة. منهجية الفيزيائيين في التجارب تنطبق تماماً على التصحيح:

  1. مراقبة الظاهرة: ما المشكلة في البرنامج؟ ما الخطأ الذي ظهر؟
  2. طرح فرضية: ما السبب المحتمل؟
  3. تصميم تجربة: كيف نتحقق من هذه الفرضية؟
  4. التحقق من النتيجة: إذا كانت الفرضية صحيحة فنصلح، وإلا نطرح فرضية أخرى

القاعدة الذهبية للتصحيح

  • أعِد الإنتاج أولاً، ثم أصلح: خطأ لا يمكن إعادة إنتاجه بشكل مستقر، لن تعرف إن كنت أصلحته فعلاً
  • غيّر متغيراً واحداً فقط في كل مرة: إذا غيّرت عدة أشياء معاً، لن تعرف أي تغيير حل المشكلة
  • ثق بالدليل، لا بالحدس: عندما تعتقد "لا يمكن أن تكون المشكلة هنا"، فعادةً تكون هنا بالضبط
  • ما الذي تغير مؤخراً؟: 80% من الأخطاء سببها تغييرات حديثة

1. قراءة رسائل الخطأ: الخطأ ليس عدوك، بل دليل

أكثر خطأ يرتكبه المبتدئون: الهلع عند رؤية خطأ وإغلاقه أو تجاهله. في الواقع، رسالة الخطأ هي البرنامج يخبرك أين المشكلة — إنه أفضل صديق لك.

1.1 الأنواع الثلاثة الرئيسية للأخطاء

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

1.2 كيف تقرأ تتبع الخطأ

باستخدام JavaScript كمثال، رسالة خطأ نموذجية:

TypeError: Cannot read properties of undefined (reading 'name')
    at getUserName (app.js:15:23)
    at handleClick (app.js:42:10)
    at HTMLButtonElement.<anonymous> (app.js:58:5)

اقرأ من الأعلى للأسفل:

  1. السطر الأول: نوع الخطأ + وصف الخطأ → TypeError، محاولة قراءة خاصية name من undefined
  2. السطر الثاني: الدالة وموقع الخطأ → دالة getUserName، السطر 15 العمود 23 في app.js
  3. الأسطر التالية: سلسلة الاستدعاءات → من استدعى هذه الدالة؟ handleClick → حدث نقر الزر

قاعدة لقراءة تتبع الخطأ

ابحث عن السبب من الأعلى للأسفل، وابحث عن المصدر من الأسفل للأعلى. السطر الأول يخبرك "ما الخطأ"، والسطر الأخير يخبرك "من أين بدأ".

1.3 مرجع سريع للأخطاء الشائعة

اسم الخطأالمعنىالأسباب الشائعة
SyntaxErrorخطأ نحويأقواس غير متطابقة، فاصلة مفقودة
TypeErrorخطأ نوعالعمل على undefined/null
ReferenceErrorخطأ مرجعياستخدام متغير غير مُعلن
RangeErrorخطأ نطاقفهرس خارج الحدود، عودية عميقة جداً
NetworkErrorخطأ شبكةفشل طلب API، مشاكل CORS
404 Not Foundالمورد غير موجودURL خاطئ، ملف محذوف
500 Internal Server Errorخطأ داخلي في الخادمكود الواجهة الخلفية تعطل

1.4 مقارنة مع أخطاء Python

تتبع Python يُقرأ بعكس JavaScript — من الأسفل للأعلى:

python
Traceback (most recent call last):
  File "main.py", line 10, in <module>
    result = calculate(data)
  File "main.py", line 5, in calculate
    return data["price"] * data["quantity"]
KeyError: 'quantity'

السطر الأخير هو سبب الخطأ: KeyError: 'quantity'، القاموس لا يحتوي على المفتاح quantity.

لغات مختلفة، نفس المنهج

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


2. أساليب التصحيح الكلاسيكية: حكمة الأجيال السابقة

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

2.1 التصحيح بالتقسيم الثنائي

الفكرة الأساسية: تقليص نطاق المشكلة للنصف، ثم للنصف، حتى الوصول للجذر.

السيناريو: الكود طويل ولا تعرف أي جزء به خطأ.

الخطوات:

  1. أضف console.log (أو print) في منتصف الكود
  2. إذا كان الخطأ قبل المنتصف → المشكلة في النصف العلوي
  3. إذا كان الخطأ بعد المنتصف → المشكلة في النصف السفلي
  4. كرر الخطوات أعلاه مع النصف الذي به المشكلة
100 سطر كود به خطأ
    ↓ أضف log عند السطر 50
المشكلة بين السطرين 50-100
    ↓ أضف log عند السطر 75
المشكلة بين السطرين 50-75
    ↓ أضف log عند السطر 62
المشكلة بين السطرين 60-62!

قوة التقسيم الثنائي

مع 100 سطر كود، تحتاج 7 تكرارات فقط (log₂100 ≈ 7) لتحديد السطر بدقة. ومع 1000 سطر تحتاج 10 فقط.

2.2 طريقة البط المطاطي

الفكرة الأساسية: اشرح المشكلة سطراً بسطر لشخص آخر (أو بطة مطاطية)، وأثناء الشرح ستكتشف الخطأ بنفسك.

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

طريقة التطبيق:

  1. افتح الكود الذي به المشكلة
  2. اشرح سطراً بسطر: "ماذا يفعل هذا السطر؟ لماذا يفعله هكذا؟"
  3. عندما تقول "همم، هنا يجب أن يكون... انتظر"، غالباً يكون الخطأ هناك

2.3 إعادة الإنتاج الأدنى

الفكرة الأساسية: تبسيط المشكلة المعقدة إلى الحد الأدنى، مع الاحتفاظ فقط بالكود اللازم لتشغيل الخطأ.

لماذا هو مهم؟

  • في النظم المعقدة، قد يكون الخطأ "مخفياً" بواسطة كود آخر
  • إعادة الإنتاج الأدنى تزيل عوامل التشويش وتجعل المشكلة واضحة
  • كما تُسهّل طلب المساعدة — لا أحد يريد مراجعة 500 سطر كود

الخطوات:

  1. أنشئ ملفاً فارغاً جديداً
  2. انسخ فقط الكود المتعلق بالمشكلة
  3. قلّص تدريجياً حتى يختفي الخطأ عند حذف أي سطر
  4. ما تبقى هو جذر الخطأ

2.4 طريقة التراجع (Git Bisect)

الفكرة الأساسية: إذا كان الكود "كان يعمل سابقاً والآن لا يعمل"، ابحث عن commit الذي أدخل المشكلة.

bash
# أداة البحث الثنائي المدمجة في Git
git bisect start
git bisect bad          # حدد النسخة الحالية بأن بها خطأ
git bisect good abc123  # حدد نسخة قديمة كانت تعمل
# سيبدّل Git تلقائياً إلى commit في المنتصف، اختبره وأخبره good أو bad
# بعد تكرار بضع مرات ستجد commit الذي أدخل الخطأ

دليل اختيار طريقة التصحيح

الحالةالطريقة الموصى بها
لا أعرف أي جزء من الكود به خطأالتقسيم الثنائي
المنطق يبدو صحيحاً لكن النتيجة خاطئةالبط المطاطي
خطأ في نظام معقدإعادة الإنتاج الأدنى
"كان يعمل ثم تعطل فجأة"التراجع / Git Bisect

3. صندوق أدوات التصحيح: الأدوات المناسبة تضاعف الكفاءة

المنهجية هي الأساس، لكن الأدوات الجيدة تضاعف كفاءة التصحيح.

3.1 console.log / print: الأبسط والأكثر عملية

السيناريو: التحقق السريع من قيم المتغيرات وتأكيد أين وصل تنفيذ الكود.

javascript
// JavaScript
console.log('تم استدعاء الدالة، المعاملات هي:', data)
console.log('نتيجة الحساب:', result)
console.table(arrayData)  // عرض المصفوفات/الكائنات في جدول
python
# Python
print(f"القيمة الحالية: {value}")
print(f"النوع: {type(data)}")  # التحقق من نوع البيانات

تقنيات متقدمة:

الطريقةالاستخدام
console.log()مخرجات عادية
console.warn()تحذير أصفر، سهل الإيجاد بين السجلات الكثيرة
console.error()خطأ أحمر
console.table()عرض المصفوفات والكائنات في جدول
console.time() / console.timeEnd()قياس وقت تنفيذ الكود
console.trace()طباعة تتبع الاستدعاءات

3.2 التصحيح بنقاط التوقف: تنفيذ سطراً بسطر

السيناريو: منطق معقد يحتاج تتبع خطوة بخطوة.

في المتصفح (Chrome DevTools):

  1. افتح أدوات المطور (F12) → لوحة Sources
  2. ابحث عن ملف المصدر، انقر على رقم السطر لوضع نقطة توقف
  3. فعّل العملية ذات الصلة، سيتوقف الكود عند نقطة التوقف
  4. استخدم أزرار التحكم للتنفيذ خطوة بخطوة:
    • متابعة (F8): التشغيل لنقطة التوقف التالية
    • خطوة فوق (F10): تنفيذ السطر الحالي دون الدخول في الدوال
    • خطوة داخل (F11): الدخول داخل الدالة
    • خطوة خارج (Shift+F11): الخروج من الدالة الحالية

في VS Code:

  1. انقر يسار رقم السطر لوضع نقطة توقف (نقطة حمراء)
  2. اضغط F5 لبدء التصحيح
  3. راجع القيم الحالية لجميع المتغيرات في لوحة "Variables"
  4. أضف التعابير التي تهمك في لوحة "Watch"

نقاط التوقف مقابل console.log

console.log مناسب للتحقق السريع، يُحذف بعد الاستخدام. نقاط التوقف مناسبة لتحليل المنطق المعقد بعمق. الاثنان لا يحل محل أحدهما الآخر بل يكمّلانه.

3.3 تصحيح الشبكة: مشاكل بين الواجهة الأمامية والخلفية

السيناريو: الصفحة لا تُعرض بشكل صحيح، لكن لست متأكداً هل المشكلة من الواجهة الأمامية أم من البيانات المُعادة من الخلفية.

Chrome DevTools → لوحة Network:

ما تراقبهما يمكنك اكتشافه
رمز الحالة404 (عنوان خاطئ)، 500 (خادم معطل)، 403 (بدون صلاحية)
معاملات الطلبهل البيانات المرسلة من الواجهة الأمامية صحيحة
بيانات الاستجابةهل تنسيق البيانات المُعادة من الخلفية صحيح
وقت الطلبأي واجهة بطيئة جداً وتبطئ الصفحة
ترويسات الطلبهل تم إرسال Token؟ هل Content-Type صحيح

قاعدة ذكرية: راجع رمز الحالة أولاً، ثم معاملات الطلب، وأخيراً بيانات الاستجابة.

3.4 مرجع سريع لأدوات التصحيح

نوع المشكلةالأداة الموصى بها
قيمة متغير خاطئةconsole.log / نقطة توقف
ترتيب تنفيذ المنطق خاطئنقطة توقف
فشل طلب APIلوحة Network
أنماط الصفحة خاطئةلوحة Elements (فحص CSS)
مشاكل الأداءلوحة Performance / console.time
تسرب الذاكرةلوحة Memory

4. التصحيح في عصر الذكاء الاصطناعي: اجعل الذكاء الاصطناعي مساعداً لك

أدوات الذكاء الاصطناعي (ChatGPT, Claude, Cursor, إلخ) يمكنها تسريع التصحيح بشكل كبير، لكن بشرط أن تعرف كيف تستخدمها.

4.1 فيما يبرع الذكاء الاصطناعي؟

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

4.2 الطريقة الصحيحة لطرح الأسئلة على الذكاء الاصطناعي

سؤال سيء:

"الكود الخاص بي به خطأ، ساعدني في مراجعته"

سؤال جيد:

"أكتب مكون نموذج بلغة React، وعند الإرسال يظهر الخطأ TypeError: Cannot read properties of undefined (reading 'email'). إليك الكود ذو الصلة: [ألصق الكود]. لقد تأكدت أن تنسيق البيانات المُعادة من API صحيح، المشكلة على الأرجح في معالجة البيانات في الواجهة الأمامية."

قالب للسؤال:

1. ماذا أفعل: [السياق]
2. السلوك المتوقع: [ما يجب أن يحدث]
3. السلوك الفعلي: [ما يحدث فعلاً]
4. رسالة الخطأ: [الخطأ الكامل]
5. الكود ذو الصلة: [ألصق الكود]
6. ما جربته: [ما استبعدته]

4.3 فخاخ التصحيح بالذكاء الاصطناعي

ثلاث فخاخ للتصحيح بالذكاء الاصطناعي

  1. قد "يتحدث بثقة عن أشياء خاطئة": الحل الذي يقدمه قد يبدو معقولاً لكنه خاطئ تماماً. تحقق دائماً بنفسك.
  2. لا يعرف سياقك: لا يعرف هيكل مشروعك، إصدارات التبعيات، أو بيئة التشغيل. عليك تزويده بسياق كافٍ.
  3. الاعتماد المفرط يُضعف قدرتك على التصحيح: إذا مررت كل خطأ مباشرة للذكاء الاصطناعي، لن تتعلم التصحيح بنفسك أبداً. ننصح بالتحليل لمدة 5 دقائق قبل طلب المساعدة من الذكاء الاصطناعي.

4.4 المزيج المثالي: الذكاء الاصطناعي + الإنسان

تصادف خطأ

الخطوة 1: اقرأ رسالة الخطأ بنفسك (1 دقيقة)

الخطوة 2: اطرح فرضية (2 دقيقة)

الخطوة 3: تحقق من الفرضية بسرعة (2 دقيقة)

هل علقت؟ → أرسل رسالة الخطأ + الكود + تحليلك للذكاء الاصطناعي

الذكاء الاصطناعي يقترح → تحكم على مدى معقوليته → تحقق

5. عقلية وعادات التصحيح: من "إطفاء الحرائق" إلى "منعها"

أفضل تصحيح هو الذي لا تحتاجه. العادات الجيدة تقلل الأخطاء من الجذور.

5.1 البرمجة الدفاعية

الفكرة الأساسية: عند كتابة الكود، افترض أن "كل شيء قد يفشل" واستعد الحماية مسبقاً.

javascript
// سيء: افتراض أن data موجود دائماً
const name = data.user.name

// جيد: كتابة دفاعية
const name = data?.user?.name ?? 'مستخدم غير معروف'
python
# سيء: افتراض أن الملف يمكن فتحه دائماً
content = open('config.json').read()

# جيد: كتابة دفاعية
try:
    content = open('config.json').read()
except FileNotFoundError:
    print("ملف التهيئة غير موجود، استخدام التهيئة الافتراضية")
    content = '{}'

5.2 كتابة سجلات جيدة

السجلات (logs) هي مفتاح "التصحيح بعد الحدث". في بيئة الإنتاج لا يمكنك وضع نقاط توقف، بل تعتمد فقط على السجلات.

مستوى السجلالاستخداممثال
DEBUGمعلومات تفصيلية أثناء التطويرقيم المتغيرات، معاملات الدوال
INFOالتدفق الطبيعي للأعمال"تسجيل دخول ناجح"، "تم إنشاء طلب"
WARNلا يؤثر على الوظيفة لكن يحتاج انتباهاً"فشل في الذاكرة المؤقتة"، "إعادة المحاولة الثانية"
ERRORحدث خطأ يحتاج معالجة"فشل الاتصال بقاعدة البيانات"، "انتهت مهلة API"

معايير السجل الجيد

السجل الجيد يجب أن يجيب: متى، أين، ماذا حدث، ما البيانات المهمة.

[2025-01-15 14:30:22] [ERROR] [OrderService] فشل إنشاء الطلب
  معرف المستخدم: 12345، معرف المنتج: 67890، السبب: نفد المخزون

5.3 قائمة فحص التصحيح

عند مواجهة خطأ، اتبع هذا الترتيب:

  1. اقرأ رسالة الخطأ: نوع الخطأ، الملف، رقم السطر
  2. ما الذي تغير مؤخراً؟: استخدم git diff لمراجعة التغييرات الحديثة
  3. هل يمكن إعادة إنتاجه؟: ابحث عن خطوات إعادة إنتاج مستقرة
  4. قلّص النطاق: استخدم التقسيم الثنائي أو إعادة الإنتاج الأدنى
  5. اطرح فرضية وتحقق منها: غيّر متغيراً واحداً فقط في كل مرة
  6. اختبار الانحدار بعد الإصلاح: تأكد أن الإصلاح لم يُدخل مشاكل جديدة

5.4 أخطاء شائعة يقع فيها المبتدئون

الفخالتصرف الصحيح
البدء بتعديل الكود دون قراءة الخطأاقرأ رسالة الخطأ كاملة أولاً
تغيير عدة أماكن في وقت واحدغيّر مكاناً واحداً فقط، تحقق ثم انتقل للتالي
عمل commit دون اختبار بعد التعديلشغّل الاختبارات بعد كل تعديل
الاختبار على جهازك فقطضع في اعتبارك بيئات مختلفة (متصفحات، أنظمة، شبكات)
عدم تنظيف console.log بعد التصحيحاحذف كل كود التصحيح قبل عمل commit
إعادة التشغيل/إعادة التثبيت عند حدوث مشاكلافهم السبب أولاً، إعادة التشغيل حل مؤقت فقط

6. الخلاصة

التصحيح حرفة تحتاج ممارسة مقصودة. لنراجع النقاط الرئيسية:

  1. التصحيح منهج علمي: مراقبة → فرضية → تجربة → تحقق، وليس حظاً
  2. رسائل الخطأ أصدقاؤك: تعلم استخراج "ما الخطأ، أين، لماذا"
  3. الأساليب الكلاسيكية لا تبلى: التقسيم الثنائي، البط المطاطي، إعادة الإنتاج الأدنى أساس كل تصحيح
  4. استخدم الأدوات المناسبة لكل موقف: console.log للتحقق السريع، نقاط التوقف للتحليل العميق، Network لفحص الواجهات
  5. الذكاء الاصطناعي مساعد وليس عكازاً: حلل بنفسك أولاً، اطلب المساعدة ثانياً، وتحقق بنفسك أخيراً
  6. الوقاية خير من العلاج: البرمجة الدفاعية وعادات السجلات الجيدة تقلل الأخطاء من الجذور

تذكر هذا

كل خطأ هو فرصة للتعلم. كل خطأ تصلحه يبني قدرتك على "التعرف على الأنماط" — في المرة القادمة عندما تواجه مشكلة مشابهة، ستحدد السبب بشكل أسرع.


قراءات إضافية