Overall Course Progress التقدم الإجمالي في الدورة 0%
0 of 15 Days Completed تم إكمال 0 من 15 يوماً Target: 1 Hour/Day المستهدف: ساعة/يوم
Day 8 اليوم 8

Tracing Execution and Debugging تتبع مسار تنفيذ الأكواد وتصحيح الأخطاء

Theory & Practical نظري وعملي 1 Hour 1 ساعة

Learning Outcomes مخرجات التعلم

  • Trace program execution step-by-step manually to explain output anomalies.
  • Use print statements strategically as a debugging tool to inspect variable states.
  • Identify logical errors hidden within loop and conditional structures.
  • Apply strict debugging discipline to fix broken mini-projects.
  • تتبع مسار تنفيذ البرنامج يدوياً خطوة بخطوة للوقوف على أسباب المخرجات غير المتوقعة.
  • استخدام جمل الطباعة (print) بشكل استراتيجي كأداة لمراقبة قيم الحالات والمتغيرات.
  • تحديد الأخطاء المنطقية (Logical Errors) المخفية في الحلقات والجمل الشرطية.
  • تطبيق منهجية صارمة لتصحيح الأخطاء وإصلاح المشاريع المصغرة المتعطلة.

1. Manual Execution Tracing (Dry-Running)

When your code doesn't produce the expected results, do not just make random edits. The most reliable way to find bugs is **manual execution tracing** (also known as "dry-running"). This is the practice of acting like the computer: reading the code line-by-line and recording how variables change state in a **trace table**.

Let's dry-run this simple calculation program:

total = 0
for i in [1, 2, 3]:
    total += i
Execution Trace Table
Figure 8.1: Step-by-step manual trace table keeping track of variables and iterations to understand execution state.
Debugging Glossary
Dry-Running: Manually stepping through program execution on paper or in your mind to locate logical anomalies.
Trace Table: A table grid where columns represent program variables and rows represent each line execution or loop iteration.

2. Strategic Print Statement Placement

A fast way to inspect your program's state at runtime is to insert strategic `print()` statements. By printing the values of your variables at key checkpoints (such as inside a loop or before an if branch), you can verify that the values match your expectations.

# Printing checkpoint statements
total = 0
print(f"[DEBUG] Initial total: {total}")
for val in [10, 20]:
    total += val
    print(f"[DEBUG] Add: {val}, Current total: {total}")
print(f"Final Output: {total}")
Strategic Print Debugging
Figure 8.2: Placing temporary debug print statements to monitor hidden variable modifications during program execution.

3. Identifying Logical Errors

Unlike **syntax errors** (which prevent your program from running), **logical errors** (bugs) occur when the program runs without crashing, but produces incorrect results. These errors are caused by flawed design rules, incorrect conditions, or wrong calculations.

Expected vs Actual Logic Divergence
Figure 8.3: Logic error divergence comparison: illustrating how wrong operators or assignment rules cause code results to deviate from expectations.
⚠️

Cleanup Debug Prints: While print debugging is extremely useful, remember to delete or comment out your `[DEBUG]` statements before publishing your final script. This keeps your user-facing console clean.

4. Resolving Assignment vs Addition Logic Bugs

A classic logic bug is resetting a variable inside a loop instead of accumulating values.

Incorrect Code (Overwriting Variable):
# Bug: = instead of += resets the variable every loop
total = 0
for i in [1, 2, 3]:
    total = i # Resets total to i, overwriting previous values!
print(total) # Outputs: 3 (Expected: 6)
Correct Code (Accumulating Variable):
# Correctly accumulates values
total = 0
for i in [1, 2, 3]:
    total += i # Correct addition
print(total) # Outputs: 6

1. التتبع اليدوي لتنفيذ الأكواد (Dry-Running)

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

لنقم بتتبع هذا البرنامج الحسابي البسيط يدوياً:

total = 0
for i in [1, 2, 3]:
    total += i
جدول تتبع الكود
الشكل 8.1: جدول تتبع يدوياً يسجل قيم المتغيرات والتكرارات خطوة بخطوة لفهم حالة تنفيذ الكود.
قاموس تتبع الأخطاء
التتبع اليدوي (Dry-Running): تتبع مسار تنفيذ الكود خطوة بخطوة في ذهنك أو على الورق لتحديد المشكلات المنطقية.
جدول التتبع (Trace Table): جدول تمثل أعمدته متغيرات البرنامج وتمثل أسطره خطوات التنفيذ أو دورات التكرار لتسجيل القيم.

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

تعتبر إضافة جمل طباعة print() مؤقتة طريقة سريعة لمعاينة حالة برنامجك أثناء التشغيل. من خلال طباعة قيم المتغيرات في مواقع رئيسية (مثل داخل حلقة التكرار أو قبل جملة if)، يمكنك التحقق مما إذا كانت القيم تطابق ما خططت له.

# إدراج جمل الطباعة للمراقبة والتتبع
total = 0
print(f"[DEBUG] Initial total: {total}")
for val in [10, 20]:
    total += val
    print(f"[DEBUG] Add: {val}, Current total: {total}")
print(f"Final Output: {total}")
طباعة جمل التتبع
الشكل 8.2: وضع جمل طباعة تتبع مؤقتة لمراقبة التغييرات غير المرئية في قيم المتغيرات أثناء تشغيل البرنامج.

3. اكتشاف الأخطاء المنطقية (Logical Errors)

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

انحراف المنطق
الشكل 8.3: مقارنة انحراف مخرجات البرنامج: يوضح كيف تؤدي المعاملات الخاطئة أو القوانين غير الدقيقة لانحراف النتيجة عن المتوقع.
⚠️

تنظيف أكواد التتبع: على الرغم من فائدة جمل الطباعة في تتبع الأخطاء، تذكر دائماً إزالة أو إخفاء جمل الطباعة الخاصة بـ [DEBUG] قبل تسليم الكود النهائي للحفاظ على نظافة مخرجات البرنامج للمستخدمين.

4. إصلاح أخطاء إعادة التخصيص بدلاً من الإضافة التراكمية

خطأ منطقي كلاسيكي يتمثل في إعادة تعيين قيمة المتغير داخل حلقة التكرار بدلاً من جمع القيم تراكمياً.

كود خاطئ (إعادة كتابة المتغير):
# خطأ: معامل التخصيص الفردي يصفر القيمة السابقة في كل دورة
total = 0
for i in [1, 2, 3]:
    total = i # يعيد تعيين total لتصبح مساوية لـ i، مما يمسح القيم السابقة!
print(total) # المخرج: 3 (بينما المتوقع: 6)
كود صحيح (الجمع التراكمي للمتغير):
# يجمع القيم تراكمياً بشكل صحيح
total = 0
for i in [1, 2, 3]:
    total += i # إضافة تراكمية صحيحة
print(total) # المخرج: 6
Practical Activity النشاط العملي

Broken Accumulator Repair إصلاح عداد تراكمي معطل

The following program is supposed to double numbers from 1 to 3 and calculate their total sum. However, it is bugged and produces the wrong output. Use dry-running and print statements to debug and fix it:

  1. Here is the bugged code:
    # Bugged script
    total = 0
    for i in range(1, 4):
        doubled = i * 2
    total = total + doubled
    print("Total sum:", total)
  2. Trace the execution of this code. Notice that the line updating the total is placed outside the loop due to a missing indent!
  3. Strategically place a debug print inside the loop to monitor doubled and total.
  4. Correct the indentation of the accumulator statement so that it runs inside the loop, and verify the output.

المفترض بالبرنامج التالي مضاعفة الأرقام من 1 إلى 3 وحساب مجموعها الإجمالي. ولكنه يحتوي على خطأ منطقي وينتج نتيجة خاطئة. استخدم مهارات التتبع البرمجي لإصلاحه:

  1. هذا هو الكود الذي يحتوي على المشكلة:
    # السكربت الذي يحتوي على الخطأ
    total = 0
    for i in range(1, 4):
        doubled = i * 2
    total = total + doubled
    print("Total sum:", total)
  2. تتبع هذا الكود يدوياً. لاحظ أن السطر المسؤول عن تحديث الإجمالي مكتوب خارج حلقة التكرار بسبب خطأ في الإزاحة والمحاذاة!
  3. أضف جملة طباعة تتبع داخل الحلقة لمراقبة المتغيرات doubled و total.
  4. قم بمحاذاة سطر الجمع التراكمي للداخل ليدخل ضمن نطاق الحلقة، وشغل البرنامج للتأكد من المخرجات.
Model Answer (Python Code)
الإجابة النموذجية (كود بايثون)
# Corrected and debugged code
total = 0

print("[DEBUG] Loop starts")
for i in range(1, 4):
    doubled = i * 2
    # Fix: Indent this statement so it runs on every loop iteration
    total = total + doubled
    print(f"[DEBUG] i: {i}, doubled: {doubled}, running total: {total}")

# Verify output: (1*2) + (2*2) + (3*2) = 2 + 4 + 6 = 12
print("Total sum:", total)

Run the code above in your Thonny or VS Code IDE. Inspect variable outputs and logic flow to ensure it behaves exactly as described. قم بتشغيل الكود أعلاه في بيئة Thonny أو VS Code. تتبع مخرجات المتغيرات ومسار المنطق للتأكد من عمل الكود بالشكل الصحيح.