ตั้งรหัส error อย่างไรให้ใช้งานได้จริง — รหัสสองประเภทที่ทำงานคู่กัน
เวลาระบบมีปัญหา ผู้ใช้จะโทรมาบอกว่า “กดแล้วขึ้นแดง ๆ” ซึ่งไล่หาไม่เจอ
ทางแก้ที่ทุกคนคิดออกคือใส่รหัสให้ผู้ใช้คัดลอกมาแจ้ง แต่คำถามที่มักไม่ถูกถามคือ — รหัสนั้นควรตอบคำถามอะไร
เราพบว่ามันมีคำถามสองข้อที่ต่างกันสิ้นเชิง และรหัสเดียวตอบทั้งสองไม่ได้
คำถามสองข้อ
| คำถาม | ต้องการรหัสแบบไหน |
|---|---|
| “เหตุการณ์นี้เกิดตอนไหน ไปดู log ครั้งนั้นได้ที่ไหน” | รหัสที่ไม่ซ้ำกันทุกครั้ง |
| “อาการแบบนี้เคยเจอไหม สาเหตุคืออะไร แก้ยังไง” | รหัสที่เหมือนเดิมทุกครั้งที่อาการเดียวกัน |
สังเกตว่าคุณสมบัติที่ต้องการขัดกันโดยตรง ข้อแรกต้องไม่ซ้ำ ข้อสองต้องซ้ำ
ระบบที่มีรหัสแบบเดียวจึงตอบได้ข้อเดียวเสมอ และมักจบลงที่การมีรหัสที่ไม่ซ้ำ ซึ่งบอกได้แค่ว่า “ไปดูตรงนี้” แต่ไม่ช่วยอะไรเลยเมื่อเป็นปัญหาที่เคยเจอมาแล้วสิบครั้ง
เราจึงมีรหัสสองประเภท
1. รหัสประจำเหตุการณ์
รูปแบบ EE-{ส่วนงาน}-{หน้าจอ}-{รหัสสุ่ม}
ออกให้ทุก error โดยอัตโนมัติ ไม่ต้องมีใครไปเขียนเพิ่ม ผู้ใช้เห็นบนหน้าจอ คัดลอกมาแจ้งได้ และทีมงานเอาไปค้นหาบันทึกของเหตุการณ์นั้นได้ตรง ๆ
ส่วน “ส่วนงาน” กับ “หน้าจอ” ที่อยู่ในรหัสมีประโยชน์ก่อนจะเปิด log ด้วยซ้ำ — เห็นรหัสก็รู้แล้วว่าปัญหาอยู่โซนไหนของระบบ
2. รหัสประจำอาการ
รูปแบบ EE-{ชั้น}-{หมวด}-{เลข}
เป็นรหัสที่คงที่ ผูกกับ “อาการ” ไม่ใช่ “ครั้ง” ใช้เมื่อเรารู้จักอาการนั้นดีพอจะบอกสาเหตุและวิธีแก้ได้
รหัสนี้เป็นของเสริม ไม่ใช่ทุก error จะมี เพราะการตั้งรหัสประจำอาการให้กับสิ่งที่ยังไม่เข้าใจก็ไม่มีประโยชน์
ตอนนี้เรามีชุดรหัสประจำอาการอยู่ 4 กลุ่มตามโดเมนงาน — งานติดตั้งและดูแลระบบ · งานเชื่อมมาร์เก็ตเพลส · งาน AI · งานเชื่อมขนส่ง
ทุกกลุ่มขึ้นต้นด้วยคำนำหน้าเดียวกัน เพื่อให้ค้นหาข้ามระบบด้วยคำเดียวได้ ซึ่งฟังดูเป็นรายละเอียดเล็ก ๆ แต่มีผลมากตอนไล่ปัญหาที่ข้ามหลายส่วน
กฎการตั้งเลข — เดาได้และค้นได้
ตัวอย่างที่ชัดที่สุดคือชุดรหัสของงานเชื่อมขนส่ง ซึ่งใช้รูปแบบ EE-ISHIP-{การกระทำ}-{เลข}
จองเลขต้น ๆ ให้ชนิดพื้นฐาน
เลข 001 ถึง 005 จองไว้ให้ความล้มเหลวพื้นฐาน 5 ชนิดเหมือนกันทุกการกระทำ
- 001 — ยืนยันตัวตนไม่ผ่าน
- 002 — เชื่อมต่อไม่ได้
- 003 — ปลายทางมีปัญหา
- 004 — อ่านคำตอบไม่ออก
- 005 — เงื่อนไขทางธุรกิจไม่ผ่าน
ผลคือเดาได้ — เห็นเลขลงท้าย 002 ก็รู้ทันทีว่าเป็นปัญหาการเชื่อมต่อ ไม่ว่าจะมาจากการกระทำไหนในทั้ง 15 แบบ และค้นได้ — อยากดูปัญหาการเชื่อมต่อทั้งหมดก็ค้นด้วยลงท้าย 002 ทีเดียว
เลข 999 สงวนไว้สำหรับกรณีที่จัดกลุ่มไม่ได้ ส่วนเลข 010 ขึ้นไปใช้กับอาการเฉพาะที่รู้จักแล้ว
กฎข้อเดียวที่ใช้ตัดสินว่าควรแยกรหัสหรือไม่
แยกรหัสเมื่อ “วิธีแก้” ต่างกัน ไม่ใช่เมื่อ “อาการ” ต่างกัน
ตัวอย่างจริงจากชุดรหัสงานขนส่ง
- ขอสิทธิ์เข้าใช้ระบบไม่ผ่าน (เลข 001) — โทเคนหมดอายุ วิธีแก้คือขอใหม่ ระบบทำเองได้
- ขอสิทธิ์ไม่ผ่านเพราะรหัสผ่านผิด (เลข 010) — อาการที่ปลายทางเหมือนกันเป๊ะ แต่วิธีแก้คนละเรื่อง ต้องมีคนไปแก้ค่าตั้งค่า ขอใหม่กี่รอบก็ไม่ผ่าน
ถ้าใช้รหัสเดียวกัน ระบบจะพยายามขอโทเคนใหม่วนไปเรื่อย ๆ และไม่มีใครรู้ว่าต้องไปแก้ค่าตั้งค่า
กฎนี้ทำให้จำนวนรหัสไม่บานปลาย เพราะอาการที่ต่างกันแต่แก้เหมือนกันก็ไม่ต้องแยก
อาการอื่นที่เราแยกรหัสด้วยเหตุผลเดียวกัน
- ตอบสำเร็จแต่ไม่มีเลขพัสดุกลับมา — ดูเหมือนสำเร็จ แต่ยังไม่มีพัสดุจริง ต้องจัดการต่างจากกรณีล้มเหลว
- ขอไฟล์ใบปะหน้าแล้วได้หน้าล็อกอินแทน — ถ้าไม่ตรวจแล้วบันทึกไปตรง ๆ จะได้ไฟล์ที่เปิดไม่ออก และไปรู้ตัวตอนจะปะกล่อง
เส้นแบ่งที่สำคัญไม่แพ้กัน — อะไรไม่ควรมีรหัส
กฎของเราคือ
- ข้อผิดพลาดจริงของระบบ → ต้องมีรหัสเสมอ
- ผู้ใช้กรอกข้อมูลไม่ครบหรือผิดเงื่อนไข → ข้อความธรรมดา ไม่ต้องมีรหัส
เหตุผลคือกรณีหลังไม่ใช่บั๊ก มันคือระบบทำงานถูกต้องแล้ว การใส่รหัสให้มันจะทำสองอย่างที่ไม่ดี — ทำให้ผู้ใช้คิดว่าระบบพัง และทำให้ระบบเฝ้าระวังเต็มไปด้วยเรื่องที่ไม่ต้องแก้จนกลบเรื่องที่ต้องแก้จริง
เส้นแบ่งนี้ดูเล็กแต่เป็นตัวชี้ขาดว่าระบบเฝ้าระวังจะใช้งานได้จริงหรือกลายเป็นเสียงรบกวนที่ทุกคนเมิน
รหัสต้องมาพร้อมข้อความที่ทำต่อได้
รหัสอย่างเดียวไม่พอ เป้าหมายของเราผูกกันสองข้อ
- ทีมงานรู้ว่าพลาดตรงไหน — ทุก error มีรหัสและบันทึกที่มีโครงสร้างส่งเข้าระบบเฝ้าระวัง ค้นย้อนหลังได้
- ผู้ใช้ที่ไม่รู้เรื่องเทคนิคเข้าใจและทำต่อได้ — ข้อความภาษาไทยที่บอกว่าเกิดอะไรและควรทำอย่างไรต่อ ไม่มีข้อความทางเทคนิคดิบ ๆ และมีรหัสให้คัดลอกแจ้ง
ข้อสองสำคัญกว่าที่หลายทีมคิด เพราะข้อความผิดพลาดคือสิ่งที่ผู้ใช้เจอในวันที่แย่ที่สุดของเขา
ทำให้เขียนตามได้จริง
ระบบรหัสจะมีค่าก็ต่อเมื่อทุกคนในทีมทำเหมือนกัน เราจึงเขียนเป็นเอกสารกลางที่ขึ้นต้นด้วยตารางสรุปว่า “ตอนนี้กำลังเขียนอะไร ให้ใช้แบบไหน” อ่านแถวเดียวจบ ไม่ต้องอ่านทั้งเอกสาร
และหลายกรณีคำตอบคือ “ไม่ต้องทำอะไร — ระบบใส่รหัสให้เอง” ซึ่งเป็นคำตอบที่ดีที่สุด เพราะสิ่งที่ต้องจำคือสิ่งที่จะถูกลืม
ตัวอย่างที่เราทำแบบนี้คือชุดเชื่อมต่อขนส่ง ที่ใส่รหัสและส่งเข้าระบบเฝ้าระวังให้เองในตัวมัน คนที่เรียกใช้ไม่ต้องจำว่าต้องบันทึกอะไร
เหตุผลที่ทำแบบนั้นมาจากบทเรียนจริง — ชุดเชื่อมต่อมาร์เก็ตเพลสรุ่นก่อนคืนผลลัพธ์แทนการโยนข้อผิดพลาด แล้วปล่อยให้ผู้เรียกเป็นคนบันทึกเอง ผลคือเส้นทางที่ดักจับแล้วแสดงข้อความให้ผู้ใช้ ไม่เคยส่งอะไรเข้าระบบเฝ้าระวังเลย
เราไปรู้ตัวตอนที่ฟีเจอร์หนึ่งล้มเหลวเงียบ ๆ อยู่นาน แล้วต้องกลับไปใส่การบันทึกทีหลัง คราวนี้เลยใส่ตั้งแต่ต้นและใส่ไว้ที่ชั้นเดียว
สรุป
ถ้าจะสรุปเป็นสามข้อ
- รหัสประจำเหตุการณ์กับรหัสประจำอาการ ตอบคนละคำถามและต้องมีทั้งคู่
- แยกรหัสเมื่อวิธีแก้ต่างกัน ไม่ใช่เมื่ออาการต่างกัน — กฎนี้ทำให้รหัสมีประโยชน์และไม่บานปลาย
- สิ่งที่ไม่ใช่บั๊กต้องไม่มีรหัส — ไม่งั้นระบบเฝ้าระวังจะเต็มไปด้วยเรื่องที่ไม่ต้องแก้
ทั้งสามข้อฟังดูเป็นเรื่องระเบียบ แต่ผลลัพธ์จริงคือเวลาที่ใช้ไล่หาปัญหา ซึ่งเป็นต้นทุนที่ลูกค้าจ่ายในรูปของการรอ
บริหารจัดการข้อมูลในองค์กร ครบในที่เดียว