| name | api-design |
| description | ออกแบบหรือรีวิว API — resource naming, status codes ที่ถูกความหมาย, pagination ตั้งแต่วันแรก, error shape เดียวทั้งแอป, idempotency — โดยอ่าน routes จริงใน codebase ก่อน เพราะ consistency กับของเดิมชนะความสวยตามตำรา Trigger on "ออกแบบ api", "รีวิว api", "วาง endpoint", "api design", or when the user is adding or changing API endpoints. |
api-design — API ที่ดีคือ API ที่เดาได้ โดยไม่ต้องเปิด docs
Phase 0 — Convention เดิมมาก่อนตำรา
ถ้าโปรเจกต์มี API อยู่แล้ว: อ่าน routes จริงทั้งหมดก่อน (routes/, controllers/, app router) แล้วสกัด convention ที่ใช้อยู่ — แอปที่ผสมสอง convention แย่กว่าแอปที่ใช้ convention เชยๆ แต่สม่ำเสมอทั้งแอป ของใหม่ต้องหน้าตาเหมือนของเก่า เว้นแต่ user สั่งยกเครื่อง
Phase 1 — Checklist ออกแบบ/รีวิว
| เรื่อง | กติกา |
|---|
| Naming | คำนามพหูพจน์ ไม่ใช่กริยา — POST /orders ไม่ใช่ /createOrder; nested ไม่เกิน 2 ชั้น (/users/:id/orders พอ ลึกกว่านั้นใช้ query/filter) |
| Status codes | 201+Location เมื่อสร้าง, 204 เมื่อไม่มี body, 400 รูปแบบผิด vs 422 ค่าไม่ผ่านกติกา, 401 ยังไม่ล็อกอิน vs 403 ล็อกอินแล้วแต่ไม่มีสิทธิ์, 409 ชนกับ state ปัจจุบัน — ห้ามตอบ 200 พร้อม {"error": ...} |
| Error shape | โครงเดียวทั้งแอป: {"error": {"code": "...", "message": "...", "details": [...]}} — code เป็น machine-readable สำหรับ client แยก case, message สำหรับคน |
| Pagination | บังคับบน collection ตั้งแต่วันแรก (เติมทีหลัง = breaking change) — cursor-based ถ้าข้อมูลโต/insert ถี่, page-based พอถ้าเล็กและมี UI แบ่งหน้า |
| Filtering/sorting | query params ตั้งชื่อสม่ำเสมอ (?status=paid&sort=-created_at) — อย่า invent DSL ใหม่ถ้าไม่จำเป็น |
| Idempotency | PUT/DELETE ต้อง idempotent โดยความหมาย; POST ที่ retry แล้วอันตราย (จ่ายเงิน, สั่งซื้อ) รองรับ Idempotency-Key |
| ค่าและเวลา | เวลา = ISO 8601 UTC เสมอ (2026-07-08T14:00:00Z); เงิน = integer หน่วยย่อย (สตางค์) ห้าม float |
| Versioning | ยังไม่มีผู้ใช้ภายนอก → ยังไม่ต้องมี /v1 ก็ได้ แต่ตัดสินใจแล้วบันทึกไว้; มีเมื่อไหร่ breaking change ต้องออก version ใหม่ ไม่แก้ของเดิมเงียบๆ |
Phase 2 — Output
- ตาราง endpoint: method · path · req body · res body · error codes ที่เป็นไปได้
- ตัวอย่าง JSON จริง ของ req/res อย่างน้อย endpoint หลัก — shape จริงมีค่ากว่าคำอธิบาย
- โหมดรีวิว: ชี้จุดที่ขัด convention ของ codebase เองเป็น
file:line เรียงตามผลกระทบ (breaking > confusing > cosmetic)
กติกา
- อย่า over-engineer — ไม่เสนอ HATEOAS, GraphQL, gRPC, event sourcing ถ้าโจทย์ไม่ได้เรียก ความเรียบง่ายที่สม่ำเสมอคือเป้า
- ระวังเปิดข้อมูลเกิน: ทุก endpoint ระบุว่าใครเรียกได้ และ response ไม่แถม field ที่ role นั้นไม่ควรเห็น (mass assignment / over-fetching)
- ถ้าแตะ endpoint เดิมที่มีคนใช้อยู่ — ระบุเสมอว่าอะไร breaking อะไร additive