Agent Dev Thai Academyprinciples · patterns · architecture

code ตอบว่า True แล้วข้อมูลหาย 26 อัน

function คืน True แต่ข้อมูลหาย เพราะไม่เคยนิยามว่า done แปลว่าอะไร เสร็จต้องแปลว่าอ่านกลับมาแล้วเจอ ไม่ใช่แค่รันจบโดยไม่ error

True

แค่นั้น. function ตอบกลับมาว่าบันทึกสำเร็จ ผมก็ปิดหน้าต่างไปทำงานอื่นต่อ

ลิงก์ 3 อันที่เพิ่ง save หายไปเงียบๆ ไม่มี error ไม่มี warning ไม่มี stack trace อะไรทั้งนั้น


𝟭. ตัวเขียนไม่รู้จักค่าที่ตัวเรียกส่งมา

ระบบเก็บลิงก์ของผมทำงานง่ายมาก อ่านไฟล์ทั้งไฟล์เข้ามา แก้ใน memory แล้วเขียนกลับทับทั้งไฟล์

ตัว render รู้จัก priority แค่ 1 ถึง 4 แต่ skill ที่เรียกใช้ดันสั่ง save มาเป็น priority 5

P5 ไม่ตรงกับช่องไหนเลย เลยไม่ถูกเขียนกลับลงไฟล์ และเพราะวิธีเขียนคือทับทั้งไฟล์ ของเก่าที่เคยอยู่ก็หายตามไปด้วย

function ยังคืนค่า True เหมือนเดิม เพราะมันทำงานจนจบโดยไม่ error

มันไม่ได้โกหก มันแค่ไม่เคยถูกสั่งให้กลับไปอ่านว่าเขียนติดจริงหรือเปล่า


𝟮. ไฟล์ log ที่กลายเป็น database โดยไม่มีใครรู้

วันเดียวกันเจออีกจุด ตอนสั่ง clear คิวลิงก์ที่อ่านแล้ว

ใน code มี list ตัดเก็บไว้แค่ 20 กับ 30 รายการล่าสุด ตอนเขียนคิดว่าเก็บไว้พอเป็นประวัติ ของจริงอยู่อีกไฟล์

ปัญหาคือไฟล์ของจริงถูกลบไปนานแล้ว ไฟล์ประวัตินี่แหละกลายเป็นที่เก็บข้อมูลตัวจริงไปเรียบร้อย

clear ทีเดียว URL หาย 26 อัน

รอดมาได้เพราะบังเอิญ copy ไว้ใน temp ก่อนหน้านั้นสิบนาที ไม่ได้รอดเพราะออกแบบมาดี


𝟯. ตัวนับที่โกหกมาหลายเดือน

อันที่สามเจ็บกว่าเพื่อน

ledger ของเพจเก็บสถานะโพสต์ไว้ 3 แบบ posted / ready / draft ตัว parser อ่านสถานะจากไฟล์ แล้วมองหาแค่คำว่า posted กับ ready

แต่ในไฟล์จริงผมพิมพ์สถานะไว้แบบนี้

**Status:** v4 FINAL, synchro is PUBLIC
**Status:** LOCKED, SCHEDULED Wed Jul 1
**Status:** v6 FINAL, baked in the hook

ไม่มีคำว่า posted สักคำ parser เลยตกลงมาที่ค่า default คือ draft

โพสต์ที่ลงไปแล้ว 22 อัน ถูกนับเป็นงานค้างมาหลายเดือน

แล้ว cron 3 ตัวที่ผมตั้งไว้เตือนเรื่องงานค้าง ก็เตือนเรื่องโพสต์ที่ลงไปแล้ววนอยู่อย่างนั้นทุกอาทิตย์

ผมนึกมาตลอดว่าตัวเองดองงาน ที่จริงตัวนับมันพัง

มีอีกไฟล์นึงบรรทัดแรกเขียนว่า SHELVED. DO NOT SHIP. ตัวเองสั่งฆ่าไปแล้วตั้งแต่มิถุนา ระบบยังนับเป็นงานค้างอยู่สองเดือน เพราะ enum สถานะไม่มีค่าไหนแปลว่า "ไม่เอาแล้ว"


𝟰. จุดที่เจ็บที่สุด

rule VERIFY BEFORE DONE อยู่ใน CLAUDE.md ผมมาตั้งนานแล้ว เคยเขียนถึงไปรอบนึง

rule นั้นไม่ได้พัง มันทำงานของมันครบ บังคับให้ verify ก่อนบอกว่าเสร็จ

ที่ไม่เคยเขียนไว้เลยคือ "เสร็จ" แปลว่าอะไร

ในหัวผม เสร็จ แปลว่าข้อมูลอยู่ในไฟล์จริง
ใน code ที่ผมเขียนเอง เสร็จ แปลว่ารันจนจบโดยไม่ error

สองอันนี้คนละเรื่องกัน แต่คืนค่าออกมาเป็น True เหมือนกันเป๊ะ

verify จะมีความหมายก็ต่อเมื่อมีนิยามให้เทียบ ถ้านิยามของ done คือไม่ crash การ verify ก็แค่ยืนยันว่าไม่ crash จริง ซึ่งมันผ่านอยู่แล้วทุกครั้ง

True ก็เป็นคำกล่าวอ้างเหมือนกัน

return value ที่บอกว่าสำเร็จ ไม่ต่างอะไรกับ AI พิมพ์มาว่า "แก้ไฟล์เรียบร้อยแล้วครับ" ทั้งคู่คือคำบอกเล่า ไม่ใช่หลักฐาน

rule ที่ไม่มีนิยามของ done คือ rule ที่ผ่านทุกครั้ง


𝟱. ทางแก้ ไม่ต้องลง library อะไร

นิยาม done ใหม่ก่อน เสร็จ ไม่ได้แปลว่าเขียนไปแล้ว แต่แปลว่าอ่านกลับมาแล้วเจอ

พอนิยามชัด โค้ดมันเขียนตัวเองเลย

def save(entry):
    write(entry)
    back = read()                      # อ่านกลับจากของจริง
    if entry['id'] not in back:
        raise IOError('write reported ok but row not found')
    return True

3 บรรทัด และมันจะจับ bug ทั้ง 3 อันข้างบนได้ตั้งแต่วันแรก


เอาไปแปะใน CLAUDE.md ได้เลย

DEFINE DONE, THEN VERIFY
- เขียน verify ไม่ได้ถ้ายังไม่นิยามว่า done แปลว่าอะไร
  "ไม่ error" ไม่ใช่นิยามของ done
- helper ไหนที่ save แล้วคืน True/OK
  ต้อง re-read แล้ว assert ว่าของอยู่จริง
- ก่อนแก้ข้อมูลหลายรายการพร้อมกัน
  commit หรือ snapshot ก่อนเสมอ
- enum สถานะต้องมีค่าที่แปลว่า "ไม่เอาแล้ว"
  ไม่งั้นของที่ตายแล้วจะค้างเป็นงานไปเป็นปี

rule ที่คุณตั้งไว้ไม่ได้พังหรอก ไปดูก่อนว่าคุณเคยนิยามคำว่าเสร็จไว้หรือเปล่า