
ตั้งชื่อ API Endpoints ยังไงให้เพื่อนร่วมทีมรัก (และคนอื่นก็ใช้ง่าย)
เคยไหมครับ เวลาต้องเข้าไปต่อ API กับระบบอื่น แล้วเจอชื่อ Endpoint ที่อ่านแล้วต้องเกาหัว? /getData
, /proc1
, /user_get_list
อะไรทำนองนี้ พอเห็นแล้วก็ท้อใจเบาๆ ว่าเราต้องเสียเวลาทำความเข้าใจมันอีกนานแค่ไหนกันนะ
การออกแบบ API ที่ดีมันไม่ใช่แค่เรื่องของการเขียนโค้ดให้ทำงานได้ แต่มันคือการสร้าง "ภาษา" กลางที่ทำให้ระบบต่างๆ และที่สำคัญคือ "คน" ในทีมคุยกันรู้เรื่อง การตั้งชื่อ Endpoint ให้ดีคือหัวใจของการออกแบบนั้นเลยครับ มันเป็นสิ่งที่ช่วยลดความสับสน ทำให้ API ของเราใช้งานง่าย คาดเดาได้ และพร้อมที่จะขยายต่อไปในอนาคตได้อย่างมั่นคง
แก่นหลักของการตั้งชื่อ Resource คือพระเอก
ในโลกของ REST API เรามองทุกอย่างเป็น "ทรัพยากร" (Resource) ดังนั้นชื่อ Endpoint ของเราควรจะบอกว่า "มันคืออะไร" ไม่ใช่ "มันทำอะไร"
ใช้คำนาม (Nouns) ไม่ใช่คำกริยา (Verbs)
เพราะ "การกระทำ" เราจะใช้ HTTP Methods (GET, POST, PUT, DELETE) เป็นตัวบอกอยู่แล้ว การใส่ Verb เข้าไปในชื่อจึงซ้ำซ้อนโดยไม่จำเป็น
- แบบนี้สิ:
GET /users
(ขอรายชื่อผู้ใช้งานทั้งหมด) - แบบนี้ไม่เอานะ:
GET /getUsers
ใช้พหูพจน์ (Plural Nouns) เป็นหลัก
ตามธรรมเนียมปฏิบัติแล้ว เรานิยมใช้คำนามพหูพจน์เพื่อหมายถึงชุดของ Resource นั้นๆ มันให้ความรู้สึกที่เป็นธรรมชาติกว่า
GET /users
-> ดึงรายชื่อผู้ใช้ทั้งหมดGET /users/{id}
-> ดึงผู้ใช้คนเดียวจากในชุดนั้นPOST /users
-> สร้างผู้ใช้ใหม่ในชุดนี้
เทคนิคทำให้ Endpoint อ่านง่ายเหมือนอ่านหนังสือ
เมื่อเรายึดหลัก "Resource" เป็นที่ตั้งแล้ว ต่อไปคือการทำให้ชื่อนั้นสื่อความหมายได้ชัดเจนที่สุดครับ
1. ใช้ขีดกลาง (-) คั่นคำ
เวลาที่ชื่อ Resource มีหลายพยางค์ ให้ใช้ขีดกลาง (hyphen/kebab-case) จะอ่านง่ายที่สุด และเป็นที่นิยมกันสากล
- แนะนำ:
/users/{id}/first-name
- ไม่แนะนำ:
/users/{id}/firstName
หรือ/users/{id}/first_name
2. ตัวอักษรพิมพ์เล็กเท่านั้น (Lowercase)
แม้ในทางเทคนิค URL บางส่วนอาจเป็น case-sensitive แต่เพื่อตัดปัญหาความสับสนและข้อผิดพลาดที่งี่เง่าที่สุดในสามโลก ให้ใช้ตัวพิมพ์เล็กทั้งหมดพอครับ มันเป็นมาตรฐานที่ปลอดภัยที่สุด
3. สร้างลำดับชั้น (Hierarchy) ให้เข้าใจง่าย
ถ้า Resource หนึ่งมีความสัมพันธ์อยู่ภายใต้ของอีก Resource หนึ่ง เราสามารถแสดงความสัมพันธ์นั้นผ่าน URL ได้เลย ทำให้ API ของเราแทบไม่ต้องเปิดเอกสารดูกันเลยทีเดียว
- ตัวอย่าง:
GET /users/{userId}/posts/{postId}
ชัดเจนว่ากำลังดู "โพสต์" ชิ้นหนึ่งของ "ผู้ใช้" คนหนึ่ง
4. หลีกเลี่ยงสิ่งที่ไม่จำเป็น
- นามสกุลไฟล์: อย่าใส่
.json
หรือ.xml
เข้าไปใน URL เด็ดขาด เราควรใช้Content-Type
Header ในการบอกประเภทของข้อมูลแทน วิธีนี้ทำให้ API เรายืดหยุ่นกว่ามาก หากอนาคตอยากจะเปลี่ยนรูปแบบข้อมูลที่ส่งกลับ - อักษรพิเศษ: นอกจากขีดกลางแล้ว ก็ไม่ต้องใส่อะไรแปลกๆ เข้าไปครับ ทำให้มันเรียบง่ายที่สุด
ดูตัวอย่างจริงกันดีกว่า (Good API Naming in Action)
เพื่อให้เห็นภาพชัดเจนขึ้น ลองมาดูตัวอย่างการออกแบบ Endpoint สำหรับระบบ E-commerce ง่ายๆ ที่มี "สินค้า" (products) และ "รีวิว" (reviews) กันครับ
การจัดการสินค้า (Products Resource)
GET /products
-> ดึงรายการสินค้าทั้งหมดGET /products?category=electronics
-> ดึงรายการสินค้าทั้งหมดในหมวดหมู่ electronicsGET /products/451
-> ดึงข้อมูลสินค้าชิ้นที่มี ID คือ 451POST /products
-> สร้างสินค้าชิ้นใหม่PUT /products/451
-> อัปเดตข้อมูลทั้งหมดของสินค้า ID 451DELETE /products/451
-> ลบสินค้า ID 451
การจัดการรีวิว (Nested Resource)
จะเห็นว่ารีวิวมีความสัมพันธ์อยู่กับสินค้า เราจึงออกแบบให้มันอยู่ภายใต้สินค้าได้เลย
GET /products/451/reviews
-> ดึงรีวิวทั้งหมดของสินค้า ID 451POST /products/451/reviews
-> สร้างรีวิวใหม่ให้กับสินค้า ID 451
จากตัวอย่าง จะเห็นว่าเราใช้แค่คำนามพหูพจน์ (products
, reviews
) และใช้ HTTP Method เป็นตัวบอกการกระทำ ทำให้ URL ของเราสะอาด อ่านง่าย และคาดเดาได้โดยไม่ต้องเปิดเอกสารเลยครับ
ข้อผิดพลาดที่เจอบ่อย (และวิธีเลี่ยง)
เมื่อรู้ว่าอะไรควรทำแล้ว มาดูกันดีกว่าว่าอะไรที่ไม่ควรทำเด็ดขาด ซึ่งเป็นข้อผิดพลาดที่เจอกันได้บ่อยๆ
- ตั้งชื่อแบบขอไปที: ชื่อ Endpoint ควรจะสื่อความหมายได้ชัดเจนในตัวเอง หลีกเลี่ยงการใช้ชื่อคลุมเครือ, คำย่อแปลกๆ, หรือศัพท์เทคนิคที่รู้กันแค่ในทีม ถ้าคนอื่นมาอ่านแล้วไม่เข้าใจทันที แสดงว่าชื่อนั้นอาจจะยังไม่ดีพอ
- ใช้ตัวพิมพ์ใหญ่ปนกับพิมพ์เล็ก: URI นั้นเป็น case-sensitive ตามมาตรฐาน RFC 3986 การใช้ตัวพิมพ์ใหญ่ปนเข้ามาจะสร้างความสับสนและนำไปสู่ข้อผิดพลาดได้ง่าย ย้ำอีกครั้งว่าใช้ตัวพิมพ์เล็กเท่านั้นครับ
- ย้ำอีกครั้ง! อย่าเอา Verb มาใส่ในชื่อ: หน้าที่ของ Endpoint คือการระบุ "ทรัพยากร" (ที่เป็นคำนาม) ส่วน "การกระทำ" (ที่เป็นคำกริยา) นั้นเป็นหน้าที่ของ HTTP method การเอา Verb มารวมในชื่อจึงเป็นการทำงานซ้ำซ้อนและน่าสับสน
- ลืมใส่เวอร์ชัน (Versioning): เมื่อ API ของเรามีการพัฒนาและเปลี่ยนแปลง การทำ Versioning เป็นเรื่องสำคัญอย่างยิ่งเพื่อรักษาความเข้ากันได้กับระบบเก่า (Backward Compatibility) การไม่ใส่เวอร์ชันอาจทำให้เมื่อเราอัปเดต API แล้วไปกระทบกับคนที่ยังใช้เวอร์ชันเก่าอยู่ได้ วิธีที่นิยมคือการระบุเวอร์ชันใน URL ไปเลย เช่น
/v1/users
เพื่อให้การเปลี่ยนแปลงในอนาคตเป็นไปอย่างราบรื่น
ความสม่ำเสมอ กฎเหล็กข้อสุดท้ายที่สำคัญที่สุด
ไม่ว่าเราจะเลือกใช้มาตรฐานไหน สิ่งที่สำคัญกว่าคือการ "ทำตามมาตรฐานนั้นอย่างสม่ำเสมอ" ในทุกๆ Endpoint ของโปรเจกต์ครับ การมีความสม่ำเสมอจะทำให้คนในทีมสามารถคาดเดาชื่อ Endpoint อื่นๆ ได้เองโดยที่ไม่ต้องคอยเปิดดูเอกสารตลอดเวลา มันช่วยลดเวลาในการเรียนรู้และทำให้การพัฒนาเร็วขึ้นอย่างไม่น่าเชื่อ
บทสรุป
การใส่ใจกับการตั้งชื่อ API Endpoint อาจดูเหมือนเป็นเรื่องเล็กน้อย แต่จริงๆ แล้วมันส่งผลกระทบมหาศาลต่อ Developer Experience ทั้งของคนในทีมและคนที่ต้องนำ API ของเราไปใช้ต่อ มันคือการลงทุนที่จ่ายผลตอบแทนคุ้มค่าในระยะยาว ช่วยลดภาระในการดูแลรักษา ทำให้ระบบขยายตัวได้ง่าย และที่สำคัญ มันบ่งบอกถึงความเป็นมืออาชีพและความใส่ใจในงานของเราครับ API ที่ดี เริ่มต้นที่ชื่อที่อ่านแล้วเข้าใจได้ทันทีนี่แหละครับ