ตัวอย่างงานแก้บั๊ก

เคสแก้บั๊กจริง

บั๊กที่เจอระหว่างทำโปรเจกต์ที่เปิดซอร์สโค้ด แต่ละเคสเขียนเหมือนรายงานที่ส่งให้ลูกค้า: อาการ สาเหตุ วิธีแก้ และวิธีพิสูจน์ว่าหายจริง

01

ปั๊มน้ำหยุดทำงานถาวร เมื่อบอร์ดเปิดต่อเนื่องครบ 49 วัน

  • ESP32
  • C++
  • Unit test
อาการ
เทสต์ที่จำลองเวลาของบอร์ดใกล้ค่าสูงสุดของ millis() พบว่าปั๊มไม่ยอมเปิด แม้ดินแห้ง ถ้าเกิดกับบอร์ดจริงคือรดน้ำไม่ได้เลยหลังเปิดเครื่องประมาณ 49.7 วัน
สาเหตุ
millis() เป็นตัวเลข 32 บิตที่วนกลับเป็น 0 ทุก 49.7 วัน โค้ดเดิมเทียบ "เวลาที่จะพักปั๊มเสร็จ" แบบตัวเลขตรง ๆ ค่าเริ่มต้น 0 จึงดูเหมือนยังพักอยู่ตลอด
วิธีแก้
วัด "เวลาที่ผ่านไปตั้งแต่เริ่ม" (now - start) ซึ่งคำนวณถูกเสมอแม้ตัวเลขวนรอบ และเก็บสถานะพักปั๊มเป็นตัวแปรแยก
ก่อนbool resting = int32_t(now - restUntil_) < 0;
...
restUntil_ = now + kPumpRestMs;
หลังif (resting_ && now - restStart_ >= kPumpRestMs)
  resting_ = false;
...
resting_ = true;
restStart_ = now;

พิสูจน์: เพิ่มเทสต์ millisWrap ที่เริ่มนับเวลาก่อนตัวเลขวนรอบ 5 วินาที รันบนคอมพิวเตอร์ด้วย make test ไม่ผ่านกับโค้ดเดิม และผ่านหลังแก้ · ดูเทสต์ · ดูโค้ด

02

กราฟยอดขายรายวันมีแค่วันแรก ที่เหลือว่าง

  • Google Sheets
  • สูตร
อาการ
ชีตรายงานรายวัน 30 วันมีตัวเลขแค่แถวแรก กราฟยอดขายจึงมีแท่งเดียว และตาราง "ขายดี 30 วัน" ของสินค้าว่างทั้งคอลัมน์
สาเหตุ
SUMIFS และ COUNTIFS ไม่กระจายผลลัพธ์เมื่ออยู่ใน ARRAYFORMULA ต่างจาก SUMIF ที่กระจายได้ จึงคำนวณแค่ค่าแรก
วิธีแก้
ใช้ MAP + LAMBDA ให้คำนวณทีละแถว สูตรยังเป็นสูตรเดียวต่อคอลัมน์ ไม่ต้องลากสูตร
ก่อน=ARRAYFORMULA(SUMIFS(รายการ!G2:G,
  รายการ!B2:B, "ขาย", รายการ!L2:L, A2:A31))
หลัง=MAP(A2:A31, LAMBDA(d,
  SUMIFS(รายการ!G2:G, รายการ!B2:B, "ขาย", รายการ!L2:L, d)))

พิสูจน์: รันสคริปต์สร้างชีตใหม่ทั้งไฟล์ แล้วตรวจกราฟ 30 วันและตารางสินค้าขายดีในชีตจริง · ดูโค้ด

03

แดชบอร์ดบอก "อัปเดต 8 วินาทีที่แล้ว" กับข้อมูลที่เก่าเป็นชั่วโมง

  • MQTT
  • JavaScript
  • IoT dashboard
อาการ
บอร์ดออฟไลน์ไปแล้วหลายชั่วโมง แต่เปิดเว็บแล้วขึ้นว่าเพิ่งอัปเดต ผู้ใช้อาจเข้าใจผิดว่าค่าบนจอเป็นค่าปัจจุบัน
สาเหตุ
ข้อมูลล่าสุดถูกเก็บไว้ที่ broker แบบ retained และถูกส่งมาทันทีที่เว็บเชื่อมต่อ โค้ดเดิมใช้ "เวลาที่ข้อความมาถึงเบราว์เซอร์" จึงดูสดเสมอ
วิธีแก้
ใช้เวลาที่บอร์ดวัดจริง (บอร์ดซิงก์เวลาจาก NTP และแนบมากับข้อมูล) ทั้งในการตัดสินว่าออนไลน์และข้อความ "อัปเดตเมื่อ" และทำปุ่มควบคุมให้จางลงเมื่อบอร์ดออฟไลน์
ก่อนreturn state.status === "online" &&
  Date.now() - state.lastAt < STALE_MS;
หลังconst dataTime = () => state.last?.ts
  ? state.last.ts * 1000 : state.lastAt;
return state.status === "online" &&
  Date.now() - dataTime() < STALE_MS;

พิสูจน์: จำลองบอร์ดส่งข้อมูลจริงผ่าน broker 45 วินาที แดชบอร์ดขึ้น "ออนไลน์" พอหยุดส่งก็กลับเป็น "ออฟไลน์" ถูกต้อง แล้วล้างข้อความทดสอบออกจาก broker · ดู commit

04

AI นับคนขี่มอเตอร์ไซค์ซ้ำเป็น "คนเดินถนน"

  • Computer vision
  • Object tracking
  • JavaScript
อาการ
คลิปสี่แยกมีมอเตอร์ไซค์ผ่านเส้นนับ แต่ยอด "คน" เพิ่มขึ้นด้วย โดยเฉพาะบนเครื่องที่ไม่มีการ์ดจอซึ่งวิเคราะห์ได้แค่ 7 เฟรมต่อวินาที
สาเหตุ
โค้ดเดิมตัดคนขี่ออกทีละเฟรมโดยดูว่ากรอบคนซ้อนกับกรอบรถสองล้อไหม ในเฟรมที่โมเดลมองไม่เห็นตัวรถ คนขี่จึงหลุดมาเป็นคนเดิน และถูกติดตามจนข้ามเส้น
วิธีแก้
ให้ตัวติดตาม (tracker) จำว่าเป้าหมายนี้ "เคยเป็นคนขี่" ข้ามเฟรม และบนเครื่องที่ใช้ CPU ให้เล่นวิดีโอช้าลงครึ่งหนึ่งเพื่อให้ได้เฟรมพอสำหรับติดตาม
ก่อนreturn dets.filter((d) => d.cls !== "person" ||
  !bikes.some((b) => overlap(d, b) > 0.25));
หลังd.rider = bikes.some((b) => overlap(d, b) > 0.25);
...
t.rider ||= !!d.rider;   // จำข้ามเฟรม
return this.tracks.filter((t) => !t.rider);

พิสูจน์: เทียบกับการนับด้วยตาทีละครึ่งวินาที คลิปมีรถข้ามเส้นจริงประมาณ 11 คัน บนการ์ดจอนับได้ 10 คัน และไม่มีคนขี่ถูกนับเป็นคนเดิน · ดู commit

05

เว็บต่อ MQTT broker ไม่ติด 2 ใน 3 ครั้ง

  • MQTT over WebSocket
  • TLS
  • วัดผล
อาการ
บางครั้งเปิดแดชบอร์ดแล้วค้างที่ "กำลังเชื่อมต่อ…" ใน log ของเบราว์เซอร์มี connack timeout
สาเหตุ
เขียนสคริปต์ทดสอบเชื่อมต่อ broker สาธารณะ 3 เจ้า เจ้าละ 3 รอบ เจ้าเดิมตอบไม่ทัน 2 ใน 3 รอบ ส่วนอีก 2 เจ้าตอบทุกครั้งภายในประมาณ 1 วินาที ปัญหาจึงอยู่ที่ broker ไม่ใช่โค้ดฝั่งเว็บ
วิธีแก้
ย้ายไป broker ที่ผ่านการวัด เปลี่ยนใบรับรอง root CA บนบอร์ด ESP32 ให้ตรงกับ broker ใหม่ แล้วตรวจ chain ด้วย openssl ก่อนใช้ (ไม่ปิดการตรวจใบรับรอง)

พิสูจน์: รันบอร์ดจริงบนตัวจำลอง Wokwi เชื่อมต่อ TLS สำเร็จ และแดชบอร์ดเห็นข้อมูลทุก 5 วินาที · ดูโค้ด

06

Log ของ Apps Script ขึ้น "ล้มเหลว" ทั้งที่ระบบทำงานถูก

  • Google Apps Script
  • Error handling
อาการ
เมื่อพนักงานกรอกขายเกินสต็อก ฟอร์มเตือนถูกต้อง แต่หน้าประวัติการทำงานของสคริปต์บันทึกว่า "ล้มเหลว" คนดูแลระบบจะแยกไม่ออกว่าอันไหนเป็นปัญหาจริง
สาเหตุ
ใช้ throw กับกรณีปกติที่คาดไว้แล้ว (สต็อกไม่พอ, กรอกเวลาผิด)
วิธีแก้
คืนผลลัพธ์ { ok: false, error } ให้ฟอร์มแสดงข้อความ และเก็บ throw ไว้สำหรับความผิดพลาดที่ไม่คาดคิดเท่านั้น

พิสูจน์: ลองขายสินค้าที่สต็อกเป็น 0 ในชีตจริง ฟอร์มเตือนเหมือนเดิม และ log บันทึกว่า "เสร็จสมบูรณ์" · ดู commit