Debugging Strategies (Debugging နည်းလမ်းများ)
B2.1.4 - Construct and use common debugging techniques.
မြန်မာလို: အသုံးများတဲ့ debugging (program ထဲက အမှားကို ရှာပြီး ပြင်ခြင်း) နည်းလမ်းတွေကို ကိုယ်တိုင် တည်ဆောက်ပြီး သုံးနိုင်ရပါမယ်။
အဓိက အယူအဆများ
Debugging ဆိုတာ program ထဲက error (အမှား) တွေ၊ တစ်နည်းအားဖြင့် bug (code ထဲက အမှား) တွေကို ရှာပြီး ပြင်တဲ့ လုပ်ငန်းစဉ်ပါ။ Error အမျိုးအစား အဓိက သုံးမျိုး ရှိပါတယ်:
| Error အမျိုးအစား | ဘယ်အချိန် ဖြစ်သလဲ | ဥပမာ |
|---|---|---|
| Syntax error (code ရေးထုံး မှားခြင်း) | Compile time (compile လုပ်ချိန်) မှာ | Semicolon ကျန်ခဲ့တာ၊ ကွင်း { } အဖွင့်အပိတ် မကိုက်တာ (Python: colon ကျန်ခဲ့တာ၊ indentation (စာကြောင်းရှေ့က ကွက်လပ်) မှားတာ) |
| Runtime error (program run နေစဉ် ဖြစ်တဲ့ error) | Program run နေစဉ် | သုညနဲ့ စားတာ၊ array (အရွယ်အစား ပုံသေ၊ အမျိုးအစားတူ ဒေတာစု) index (နေရာအမှတ်) က အပိုင်းအခြား ကျော်သွားတာ |
| Logic error (စဉ်းစားပုံ အမှား) | Program run ပေမယ့် ရလဒ် မှားတဲ့အခါ | <= အစား < ကို သုံးတာ၊ ပုံသေနည်း မှားတာ |
Logic error တွေက ရှာရ အခက်ဆုံးပါ၊ ဘာလို့လဲဆိုတော့ program က compile ဖြစ်ပြီး crash (program ရုတ်တရက် ပျက်ပြီး ရပ်သွားခြင်း) မဖြစ်ဘဲ run နေလို့ပါ: ရလဒ် မှားတာပဲ ထွက်လာတာပါ။ အောက်က နည်းလမ်းတွေက အဲဒီ အမှားတွေကို လိုက်ရှာဖို့ ကူညီပါတယ်။
နည်းလမ်း 1: Print statement (output ထုတ်ပြတဲ့ code line) များ
Program run နေစဉ် variable (တန်ဖိုး သိမ်းထားတဲ့ နာမည်ပေးထားတဲ့ နေရာ) တွေရဲ့ တန်ဖိုးကို စစ်ကြည့်ဖို့ အရေးကြီးတဲ့ နေရာတွေမှာ System.out.println() (Python: print()) ကို ထည့်ပါ။
ဥပမာ: Logic error ကို ရှာခြင်း
ဒီ code က array တစ်ခုရဲ့ ပျမ်းမျှကို ရှာရမှာပါ၊ ဒါပေမယ့် crash ဖြစ်ပါတယ်၊ အဲဒါကို ပြင်ပြီးတဲ့အခါမှာလည်း အဖြေ မှားထွက်ပါတယ်:
int[] scores = {80, 90, 70, 85, 96};
int sum = 0;
for (int i = 0; i <= scores.length; i++) { // Bug here!
sum += scores[i];
}
double average = sum / scores.length; // Bug here too!
System.out.println("Average: " + average);
scores = [80, 90, 70, 85, 96]
total = 0 # "sum" is a built-in function name in Python, so we use total
for i in range(len(scores) + 1): # Bug here! (the twin of Java's <=)
total = total + scores[i]
average = total // len(scores) # Bug here too! (// floors the answer)
print("Average:", average)
စုံစမ်းဖို့ print statement တွေ ထည့်ပါ:
int[] scores = {80, 90, 70, 85, 96};
int sum = 0;
for (int i = 0; i <= scores.length; i++) {
System.out.println("i = " + i); // DEBUG
System.out.println("scores[i] = " + scores[i]); // DEBUG
sum += scores[i];
System.out.println("sum = " + sum); // DEBUG
}
System.out.println("Final sum: " + sum); // DEBUG
double average = sum / scores.length;
System.out.println("Average: " + average);
scores = [80, 90, 70, 85, 96]
total = 0
for i in range(len(scores) + 1):
print("i =", i) # DEBUG
print("scores[i] =", scores[i]) # DEBUG
total = total + scores[i]
print("sum =", total) # DEBUG
print("Final sum:", total) # DEBUG
average = total // len(scores)
print("Average:", average)
ဒါကို run ကြည့်ရင် ဒါတွေကို တွေ့ရပါတယ်:
iက 5 အထိ ရောက်သွားလို့ArrayIndexOutOfBoundsExceptionဖြစ်ပါတယ် →<=ကို<အဖြစ် ပြင်ပါsum / scores.lengthက integer division (ကိန်းပြည့် အစား) ကို သုံးပါတယ် →(double) sum / scores.lengthအဖြစ် ပြင်ပါ
(Python မှာလည်း အလားတူပါ: i က 5 ရောက်ပြီး IndexError ဖြစ်ပါတယ် → range(len(scores) + 1) ကို range(len(scores)) အဖြစ် ပြင်ပါ။ // က ပျမ်းမျှကို ငယ်ဘက် ကိန်းပြည့်ဆီ ယူလိုက်ပါတယ် (floor) → / ကို သုံးပါ။)
Bug တွေကို ပြင်ပြီးရင် code ကို မတင်သွင်းခင် debug print statement တွေကို ဖယ်ထုတ်ပါ။
နည်းလမ်း 2: Trace table (variable တန်ဖိုးတွေကို အဆင့်ဆင့် မှတ်တဲ့ ဇယား) များ
Trace table က line တစ်ကြောင်း run ပြီးတိုင်း variable အားလုံးရဲ့ တန်ဖိုးကို မှတ်သွားပါတယ်။ ဒါက IB Paper 2 (IB Computer Science စာမေးပွဲမှာ programming မေးခွန်းတွေ ပါတဲ့ စာစောင်) အတွက် မဖြစ်မနေ လိုအပ်တဲ့ ကျွမ်းကျင်မှုပါ။
ဥပမာ: စာရွက်ပေါ်မှာ ကိုယ်တိုင် trace လုပ်ခြင်း
int x = 5;
int y = 3;
int z = x + y;
x = z * 2;
y = x - z;
x = 5
y = 3
z = x + y
x = z * 2
y = x - z
| Line | x | y | z |
|---|---|---|---|
int x = 5 | 5 | - | - |
int y = 3 | 5 | 3 | - |
int z = x + y | 5 | 3 | 8 |
x = z * 2 | 16 | 3 | 8 |
y = x - z | 16 | 8 | 8 |
ဥပမာ: Loop (ထပ်ခါထပ်ခါ run တဲ့ code အပိုင်း) ကို trace လုပ်ခြင်း
int total = 0;
for (int i = 1; i <= 4; i++) {
total += i;
}
total = 0
for i in range(1, 5):
total = total + i
| Iteration (loop တစ်ပတ်) | i | total (loop body run ပြီးနောက်) |
|---|---|---|
| 1 | 1 | 1 |
| 2 | 2 | 3 |
| 3 | 3 | 6 |
| 4 | 4 | 10 |
Loop တွေကို trace လုပ်တဲ့အခါ: loop variable ကို အရင် ရေးပါ၊ ပြီးရင် expression (တွက်ချက်မှု ဖော်ပြချက်) တစ်ခုချင်းကို လက်ရှိ တန်ဖိုးတွေနဲ့ တွက်ပါ။ Loop body (loop ထဲက code) run ပြီးတဲ့အခါ ပြောင်းသွားတဲ့ တန်ဖိုးတွေကို မှတ်ပါ။
နည်းလမ်း 3: Breakpoint (program ကို ခဏ ရပ်ခိုင်းတဲ့ အမှတ်အသား) နဲ့ step-through (တစ်ကြောင်းချင်း run ကြည့်ခြင်း)
IDE (code ရေးပြီး run ဖို့ သုံးတဲ့ software၊ ဥပမာ BlueJ၊ IntelliJ ဒါမှမဟုတ် VS Code) ထဲမှာ ဒါတွေကို လုပ်လို့ရပါတယ်:
- Breakpoint သတ်မှတ်ပါ: program ရပ်စေချင်တဲ့ နေရာကို မှတ်ဖို့ line number ဘေးမှာ click နှိပ်ပါ
- Debug mode နဲ့ run ပါ: program က breakpoint ကို ရောက်တဲ့အထိ run ပါတယ်
- Step through လုပ်ပါ: line တစ်ကြောင်းချင်း run ပြီး variable တန်ဖိုးတွေကို စစ်ကြည့်ပါ
- Variable တွေကို watch လုပ်ပါ (စောင့်ကြည့်ပါ): တစ်ဆင့်ချင်း run သွားရင်း တန်ဖိုးတွေ ချက်ချင်း ပြောင်းသွားတာကို ကြည့်ပါ
| လုပ်ဆောင်ချက် | ဘာလုပ်သလဲ |
|---|---|
| Breakpoint | သတ်မှတ်ထားတဲ့ line မှာ program ကို ခဏ ရပ်ပါတယ် |
| Step Over | လက်ရှိ line ကို run ပြီး နောက် line ကို သွားပါတယ် |
| Step Into | Method (သီးခြား အလုပ်တစ်ခု လုပ်ပေးတဲ့ code အပိုင်း) call ထဲကို ဝင်ပြီး အထဲမှာ trace လုပ်ပါတယ် |
| Continue | နောက် breakpoint ဒါမှမဟုတ် program အဆုံးအထိ run ပါတယ် |
IB စာမေးပွဲတွေမှာ IDE မရှိပါဘူး။ စာရွက်ပေါ်မှာ trace table တွေကို လေ့ကျင့်ပါ: စာမေးပွဲမှာ breakpoint အစား သုံးရတာ trace table ပါ။
အဖြစ်များတဲ့ bug ပုံစံများ
Off-by-one Error (တန်ဖိုး တစ် လွဲနေတဲ့ အမှား) များ
// Bug: <= causes ArrayIndexOutOfBoundsException
for (int i = 0; i <= arr.length; i++) { // should be <
// Bug: starts at 1, skips first element
for (int i = 1; i < arr.length; i++) { // should start at 0
// Bug: misses last element
for (int i = 0; i < arr.length - 1; i++) { // should be < arr.length
# Bug: the + 1 causes IndexError on the last pass
for i in range(len(arr) + 1): # should be range(len(arr))
# Bug: starts at 1, skips the first element
for i in range(1, len(arr)): # should start at 0
# Bug: misses the last element
for i in range(len(arr) - 1): # should be range(len(arr))
ပထမ loop က <= ကြောင့် ArrayIndexOutOfBoundsException ဖြစ်ပါတယ် (< ဖြစ်ရပါမယ်)။ ဒုတိယ loop က 1 ကနေ စလို့ ပထမ element (အစုထဲက အချက်) ကို ကျော်သွားပါတယ် (0 ကနေ စရပါမယ်)။ တတိယ loop က နောက်ဆုံး element ကို လွတ်သွားပါတယ် (< arr.length ဖြစ်ရပါမယ်)။ (Python မှာ range(len(arr) + 1) က နောက်ဆုံးအပတ်မှာ IndexError ဖြစ်စေပါတယ်။)
Integer Division (ကိန်းပြည့် အစား)
int a = 7, b = 2;
double result = a / b; // Bug: result is 3.0, not 3.5
double result = (double) a / b; // Fix: cast to double first
a = 7
b = 2
result = a // b # Bug (Python version): // floors the answer - 3, not 3.5
result = a / b # Fix: / always gives the decimal answer, no cast needed
a / b က ကိန်းပြည့် နှစ်ခုကို စားလို့ ရလဒ်က 3.5 မဟုတ်ဘဲ 3.0 ဖြစ်ပါတယ်။ ပြင်နည်းက double ကို အရင် cast (type ပြောင်း) လုပ်တာပါ။ (Python မှာတော့ // က ငယ်ဘက် ကိန်းပြည့်ဆီ ယူလို့ 3 ရပြီး / က ဒသမ အဖြေကို အမြဲ ပေးတဲ့အတွက် cast မလိုပါဘူး။)
= နဲ့ == ကို ရောထွေးခြင်း
if (x = 5) { ... } // Bug: assignment, not comparison
if (x == 5) { ... } // Fix: use ==
if x = 5: # Bug: assignment, not comparison - Python refuses to run this (SyntaxError)
if x == 5: # Fix: use ==
= က assignment (variable ထဲ တန်ဖိုး ထည့်ခြင်း) ပါ၊ နှိုင်းယှဉ်တာ မဟုတ်ပါဘူး။ နှိုင်းယှဉ်ဖို့ == ကို သုံးပါ။ (Python က if x = 5: ကို run မပေးဘဲ SyntaxError ပြပါတယ်။)
String တွေကို == နဲ့ နှိုင်းယှဉ်ခြင်း
if (name == "Alice") { ... } // Bug: compares references
if (name.equals("Alice")) { ... } // Fix: compares content
# Python: == compares string CONTENT, so it is the correct choice here
if name == "Alice": # correct in Python - there is no .equals()
Java မှာ == က reference (object ရှိတဲ့ memory နေရာကို ညွှန်းထားတာ) တွေကို နှိုင်းယှဉ်လို့ မှားပါတယ်၊ .equals() က အကြောင်းအရာကို နှိုင်းယှဉ်ပါတယ်။ (Python မှာတော့ == က string ရဲ့ အကြောင်းအရာကို နှိုင်းယှဉ်လို့ မှန်ပါတယ်၊ .equals() မရှိပါဘူး။)
Quick Check (အမြန် စစ်ဆေးမေးခွန်း)
Q1. Program တစ်ခုက compile ဖြစ်ပြီး run ပေမယ့် output (program က ထုတ်ပြတဲ့ ရလဒ်) မှားထွက်ပါတယ်။ ဒါက ဘယ်လို error အမျိုးအစားလဲ။
Q2. Trace table ရဲ့ ရည်ရွယ်ချက်က ဘာလဲ။
Q3. for (int i = 0; i <= arr.length; i++) မှာ ဘာမှားနေသလဲ။
Q4. IDE ထဲမှာ breakpoint က ဘာလုပ်သလဲ။
Trace Exercise (code ကို တစ်ဆင့်ချင်း လိုက်ကြည့်ခြင်း)
ဒီ code ကို trace လုပ်ပါ။ Line တစ်ကြောင်း ပြီးတိုင်း variable တစ်ခုချင်းစီရဲ့ တန်ဖိုးကို ဖြည့်ပါ။
int a = 12;
int b = 5;
int c = a % b;
a = a - c;
b = a / b;
a = 12
b = 5
c = a % b
a = a - c
b = a // b # Java's whole-number division - Python needs //
| Line | a | b | c |
|---|---|---|---|
int a = 12 | - | - | |
int b = 5 | 12 | - | |
int c = a % b | 12 | 5 | |
a = a - c | 5 | 2 | |
b = a / b | 10 | 2 |
Trace Exercise 2: Bug ကို ရှာပါ
ဒီ code က 1 ကနေ 5 အထိ ပေါင်းလဒ်ကို print ထုတ်ရမှာပါ (ရရမယ့် အဖြေ: 15)။ Bug ကို ရှာဖို့ trace လုပ်ပါ။
int sum = 0;
for (int i = 0; i < 5; i++) {
sum += i;
}
System.out.println("Sum: " + sum);
total = 0 # "sum" is a built-in function name in Python, so we use total
for i in range(0, 5):
total = total + i
print("Sum:", total)
| Iteration | i | body run ပြီးနောက် sum |
|---|---|---|
| 1 | ||
| 2 | ||
| 3 | ||
| 4 | ||
| 5 |
Output က Sum: ရဲ့ နောက်မှာ print ထုတ်တဲ့ ဂဏန်း (ဂဏန်းကိုပဲ ရိုက်ထည့်ပါ):
Bug: loop က 1+2+3+4+5 အစား ကို ပေါင်းနေပါတယ် (အဲဒီ ပုံစံအတိုင်း space မပါဘဲ ရေးပါ)။ ပြင်နည်း: i = 0; i < 5 ကို i = 1; i <= 5 အဖြစ် ပြောင်းပါ။
Spot the Error (အမှား ရှာခြင်း)
ဒီ code က element တစ်ခုချင်းစီကို အခုထိ တွေ့ထားတဲ့ အကြီးဆုံး တန်ဖိုး (running maximum) နဲ့ နှိုင်းယှဉ်ပြီး array ထဲက အကြီးဆုံး ဂဏန်းကို ရှာရမှာပါ၊ ဒါပေမယ့် အကြီးဆုံး တန်ဖိုးရဲ့ စတန်ဖိုးကို မှားပြီး သတ်မှတ်ထားပါတယ်။ ဒါက အသုံးများတဲ့ debugging ပုံစံ တစ်ခုကို စစ်ပါတယ်: accumulator variable (တန်ဖိုးတွေကို စုဆောင်း မှတ်သားသွားတဲ့ variable) တွေအတွက် မှန်ကန်တဲ့ စတန်ဖိုး (initial value) ကို ရွေးခြင်းပါ။ Bug ကို ရှာပါ။
int[] nums = {-3, -7, -2, -9, -5};
int max = 0;
for (int i = 0; i < nums.length; i++) {
if (nums[i] > max) {
max = nums[i];
}
}ဘာမှားနေသလဲ၊ ဘယ်လို ပြင်မလဲ။
Practice Exercises (လေ့ကျင့်ခန်းများ)
Core (အခြေခံ အဆင့်)
- Trace လေ့ကျင့်ခန်း။ ဒီ code အတွက် trace table ကို ဖြည့်ပါ:
int a = 8; int b = 3; int c = a / b; a = a % b; b = c + a;a = 8 b = 3 c = a // b a = a % b b = c + a - Bug ကို ရှာပါ။ ဒီ code က 1 ကနေ 10 အထိ ဂဏန်းတွေကို print ထုတ်ရမှာပါ၊ ဒါပေမယ့် မှန်မှန်ကန်ကန် အလုပ်မလုပ်ပါဘူး။ Bug ကို ရှာပြီး ပြင်ပါ:
for (int i = 1; i < 10; i++) { System.out.println(i); }for i in range(1, 10): print(i) - Debug print တွေ ထည့်ပါ။ Array တစ်ခုရဲ့ ပျမ်းမျှကို တွက်တဲ့ program တစ်ခု ပေးထားရင် loop တစ်ပတ်တိုင်းမှာ
i၊arr[i]နဲ့sumကို လိုက်ကြည့်ဖို့ print statement တွေ ထည့်ပါ။
Extension (တိုးချဲ့ အဆင့်)
- Nested loop (loop ထဲမှာ ထပ်ပါတဲ့ loop) ကို trace လုပ်ပါ။ ဒီ code ကို trace လုပ်ပြီး output အပြည့်အစုံကို ရေးပါ:
for (int i = 1; i <= 3; i++) { for (int j = 1; j <= i; j++) { System.out.print(i * j + " "); } System.out.println(); }for i in range(1, 4): for j in range(1, i + 1): print(i * j, end=" ") print() - Bug သုံးခုကို ပြင်ပါ။ ဒီ program မှာ မတူတဲ့ bug သုံးခု (syntax၊ runtime နဲ့ logic) ရှိပါတယ်။ သုံးခုလုံးကို ရှာပြီး ပြင်ပါ:
int[] data = {10, 20, 30, 40, 52} int sum = 0; for (int i = 0; i <= data.length; i++) { sum += data[i]; } double avg = sum / data.length; System.out.println("Average: " + avg);
အတန်းထဲမှာ လေ့ကျင့်ခြင်း
Debugging က autograder (အဖြေကို အလိုအလျောက် စစ်ပေးတဲ့ system) ဆီ အဖြေ တင်ရုံနဲ့ ရတဲ့ ကျွမ်းကျင်မှု မဟုတ်ပါဘူး၊ code ကို run ပြီး စစ်ကြည့်ရင်း တည်ဆောက်ရတဲ့ ကျွမ်းကျင်မှုပါ။ အပေါ်က Practice Exercises တွေကို BlueJ ဒါမှမဟုတ် VSCode နဲ့ လုပ်ကြည့်ပါ:
- Breakpoint တွေ သတ်မှတ်ပါ၊ step through လုပ်ပါ၊ variable တွေ line တစ်ကြောင်းချင်း ပြောင်းသွားတာကို watch လုပ်ပါ (လေ့ကျင့်ခန်း 1 နဲ့ 4 ရဲ့ trace table တွေ)။
- Bug ပါတဲ့ code ကို run ပါ၊ မှားထွက်တဲ့ output ဒါမှမဟုတ် stack trace (error ဖြစ်တဲ့ နေရာကို ပြတဲ့ method call စာရင်း) ကို ကြည့်ပါ၊ ပြီးရင် မပြင်ခင် debugger ဒါမှမဟုတ် print statement တွေကို သုံးပြီး အမှား ရှိတဲ့ နေရာကို ရှာပါ (လေ့ကျင့်ခန်း 2 နဲ့ 5)။
- Loop အပတ်တွေ တစ်လျှောက် variable တန်ဖိုးတွေကို လိုက်ကြည့်ဖို့ print statement တွေ ထည့်ပါ (လေ့ကျင့်ခန်း 3)။ ဘာကို print ထုတ်မလဲ ကိုယ်တိုင် ရွေးရတာ ကိုက သင်ခန်းစာပါ။
ဒီခေါင်းစဉ်အတွက် အလိုအလျောက် စစ်ပေးတဲ့ GitHub Classroom assignment မရှိပါဘူး: debugging ကို ဆရာနဲ့ အတူ တိုက်ရိုက် လုပ်တာ ဒါမှမဟုတ် ကိုယ်ပိုင် editor (code ရေးတဲ့ program) ထဲမှာ လုပ်တာ အကောင်းဆုံးပါ။
ဆက်စပ် ခေါင်းစဉ်များ
အရင် သိထားရမှာများ:
- Variables & Data Types (variable နဲ့ data type များ): variable တန်ဖိုးတွေကို နားလည်ခြင်း
- Exception Handling (exception တွေကို ကိုင်တွယ်ခြင်း): runtime error တွေက bug အမျိုးအစား တစ်ခုပါ
ဆက်စပ် ခေါင်းစဉ်များ:
- Iteration (ထပ်ခါထပ်ခါ လုပ်ခြင်း): off-by-one error တွေ အဖြစ်များတာ loop တွေမှာပါ
- 1D Arrays (တန်းတစ်တန်းတည်းမှာ စီထားတဲ့ ဒေတာအစု): array ရဲ့ အပိုင်းအခြား ကျော်တဲ့ error တွေက အဖြစ်များတဲ့ bug တွေပါ
အဆင့်တိုင်းမှာ ပြောင်းသွားတဲ့ တန်ဖိုးတွေကို မှတ်ပြီး trace table တွေကို လေ့ကျင့်ပါ၊ ပြီးရင် ကိုယ်ခန့်မှန်းထားတဲ့ output ကို program ရဲ့ output နဲ့ နှိုင်းယှဉ်ကြည့်ပါ။