APIs ทำหน้าที่เป็นโครงข่ายเชื่อมโยงของซอฟต์แวร์สมัยใหม่ ทำให้ระบบที่แตกต่างกันสามารถสื่อสารกันได้อย่างราบรื่น อย่างไรก็ตาม ความแตกต่างระหว่าง API ที่นักพัฒนาให้ความยอมรับกับ API ที่พวกเขาจำใจใช้ ขึ้นอยู่กับการออกแบบทั้งหมด API ที่ได้รับการสร้างสรรค์อย่างพิถีพิถันจะช่วยเร่งการพัฒนา ลดความขัดแย้งในการรวมระบบ และปรับขนาดได้ดีเมื่อเวลาผ่านไป API ที่ออกแบบมาไม่ดีจะกลายเป็นแหล่งที่มาของความหงุดหงิด บั๊ก และหนี้ทางเทคนิคอย่างต่อเนื่อง
ทำความเข้าใจพื้นฐานการออกแบบ API
การออกแบบ API หมายถึงการตัดสินใจอย่างรอบคอบเมื่อกำหนดว่าส่วนประกอบซอฟต์แวร์สื่อสารกันอย่างไร กระบวนการนี้ครอบคลุมโครงสร้างของปลายทาง รูปแบบข้อมูล กลไกการตรวจสอบสิทธิ์ และกลยุทธ์การจัดการข้อผิดพลาด ทุกการตัดสินใจที่ทำระหว่างการออกแบบจะหล่อหลอมประสบการณ์ของนักพัฒนา
ขั้นตอนการออกแบบเกิดขึ้นก่อนที่การนำไปใช้งานจะเริ่มขึ้น การปฏิบัติต่อ API เหมือนผลิตภัณฑ์มากกว่าการคิดเอาไว้ทีหลัง จะเปลี่ยนวิธีการที่องค์กรเข้าถึงการพัฒนา เมื่อผู้มีส่วนได้ส่วนเสียร่วมมือกันตั้งแต่เนิ่นๆ ในสัญญา API อินเทอร์เฟซที่ได้จะตอบสนองกรณีการใช้งานจริงได้ดีขึ้น แทนที่จะสะท้อนโครงสร้างฐานข้อมูลภายใน
การออกแบบที่ดีให้ความสำคัญกับผู้บริโภคโดยการจัดหา API ที่ผู้บริโภคควรทำความเข้าใจโดยสัญชาตญาณ โดยมีเอกสารประกอบน้อยที่สุด ความสามารถในการคาดการณ์มีความสำคัญสูงสุด—เมื่อนักพัฒนาเรียนรู้วิธีการทำงานของปลายทางหนึ่ง พวกเขาควรคาดหวังรูปแบบที่คล้ายกันทั่วทั้ง API ได้อย่างสมเหตุสมผล
หลักการสำคัญที่นำไปสู่การออกแบบ API ที่มีประสิทธิภาพ
หลักการพื้นฐานหลายประการเป็นแกนหลักของการออกแบบ API ที่ประสบความสำเร็จ สิ่งเหล่านี้ไม่ใช่กฎที่ตายตัว แต่เป็นปรัชญาชี้นำที่ให้ข้อมูลในการตัดสินใจตลอดวงจรการพัฒนา
ความสอดคล้องกันถือเป็นหลักการที่สำคัญที่สุด การตั้งชื่อที่เป็นมาตรฐาน โครงสร้าง URL ที่คาดเดาได้ และรูปแบบการตอบสนองที่เป็นมาตรฐานช่วยลดภาระทางความคิด เมื่อ /users คืนค่าคอลเลกชัน นักพัฒนาคาดหวังว่า /orders จะทำงานในลักษณะเดียวกัน การผสมผสานรูปแบบ—เช่น อาจคืนค่าอาร์เรย์สำหรับบางปลายทางและออบเจกต์สำหรับปลายทางอื่น—สร้างความสับสนโดยไม่จำเป็น
ความเรียบง่ายเสริมด้วยความสอดคล้องกัน ปลายทางแต่ละจุดควรมีวัตถุประสงค์ที่ชัดเจนและมุ่งเน้น ปลายทางที่ซับซ้อนเกินไปซึ่งพยายามจัดการการดำเนินการหลายอย่างที่ไม่เกี่ยวข้องกันจะกลายเป็นเรื่องยากในการจัดทำเอกสาร การทดสอบ และการบำรุงรักษา การแยกความรับผิดชอบที่ชัดเจนช่วยให้นักพัฒนาสามารถใช้เหตุผลเกี่ยวกับ API ได้อย่างมีประสิทธิภาพมากขึ้น
ความปลอดภัยจะต้องถูกผนวกรวมเข้ากับการออกแบบตั้งแต่เริ่มต้น ไม่ใช่การเพิ่มเข้ามาภายหลัง กลไกการตรวจสอบสิทธิ์ การตรวจสอบการอนุญาต และกลยุทธ์การตรวจสอบความถูกต้องของข้อมูลป้อนเข้า จะหล่อหลอมวิธีการที่ API จัดการข้อมูลที่ละเอียดอ่อน การติดตั้งความปลอดภัยเพิ่มเติมเข้ากับการออกแบบ API ที่มีอยู่มักนำไปสู่ช่องโหว่และการป้องกันที่ไม่สอดคล้องกัน
การออกแบบที่เน้นทรัพยากรในการปฏิบัติ
RESTful API จัดระเบียบตามทรัพยากร ซึ่งเป็นเอนทิตีเชิงแนวคิดที่แสดงถึงออบเจกต์โดเมนทางธุรกิจ ทรัพยากรถูกระบุด้วย URI และจัดการผ่านเมธอด HTTP มาตรฐาน แนวทางที่เน้นทรัพยากรนี้สอดคล้องกับวิธีที่นักพัฒนาคิดเกี่ยวกับข้อมูลโดยธรรมชาติ
พิจารณาแพลตฟอร์มอีคอมเมิร์ซ ทรัพยากรหลักอาจรวมถึงผลิตภัณฑ์ คำสั่งซื้อ ลูกค้า และรีวิว ทรัพยากรแต่ละประเภทจะได้รับคอลเลกชันปลายทางของตัวเอง:
GET /products
GET /products/{id}
POST /products
PUT /products/{id}
DELETE /products/{id}
โครงสร้าง URL ควรสื่อถึงคำนาม (ทรัพยากร) มากกว่าการกระทำ การดำเนินการเช่นการสร้างหรือลบควรถุกจัดการผ่านเมธอด HTTP (เช่น POST หรือ DELETE) แทนที่จะรวมไว้ใน URL เอง
ด้วยการแยกทรัพยากร (URLs) ออกจากการกระทำ (HTTP methods) ทำให้ API สะอาดขึ้น สอดคล้องกันมากขึ้น และนักพัฒนาเข้าใจและใช้งานได้ง่ายขึ้น
ความสัมพันธ์ของทรัพยากรสมควรได้รับการพิจารณาอย่างรอบคอบ เมื่อทรัพยากรหนึ่งเป็นส่วนหนึ่งของอีกทรัพยากรหนึ่ง—เช่น คำสั่งซื้อที่เป็นของลูกค้า—URLs ที่ซ้อนกันจะสื่อถึงลำดับชั้นนี้ได้อย่างชัดเจน:
GET /customers/{customer_id}/orders
POST /customers/{customer_id}/orders
อย่างไรก็ตาม การซ้อนควรคงความตื้นเอาไว้ ลำดับชั้นที่ลึกเกินไปสร้าง URL ที่จัดการยาก และอาจบ่งบอกถึงปัญหาในการสร้างโมเดล โดยทั่วไป การจำกัดการซ้อนไว้ที่หนึ่งหรือสองระดับจะช่วยรักษาความชัดเจนในขณะที่แสดงความสัมพันธ์ที่มีความหมาย
การควบคุมเมธอด HTTP และความหมายของมัน
เมธอด HTTP มีความหมายเชิงความหมายที่นักพัฒนาคาดหวังให้ได้รับการเคารพ การใช้เมธอดเหล่านี้ในทางที่ผิดจะทำลายความสามารถในการคาดเดาและอาจทำให้เกิดบั๊กที่ละเอียดอ่อนในแอปพลิเคชันไคลเอ็นต์
| เมธอด | วัตถุประสงค์ | Idempotent | ปลอดภัย |
|---|---|---|---|
| GET | ดึงข้อมูลทรัพยากร | ใช่ | ใช่ |
| POST | สร้างทรัพยากรใหม่ | ไม่ | ไม่ |
| PUT | แทนที่ทรัพยากรทั้งหมด | ใช่ | ไม่ |
| PATCH | อัปเดตทรัพยากรบางส่วน | อาจแตกต่างกัน | ไม่ |
| DELETE | ลบทรัพยากร | ใช่ | ไม่ |
คำขอ GET ดึงข้อมูลโดยไม่แก้ไขสถานะของเซิร์ฟเวอร์ ควรปลอดภัย—การเรียก GET /users ซ้ำๆ จะต้องไม่เปลี่ยนแปลงข้อมูลใดๆ คุณสมบัตินี้ช่วยให้สามารถแคช บุ๊กมาร์ก และดึงข้อมูลล่วงหน้าได้ เมื่อปลายทาง GET กระตุ้นผลข้างเคียง เช่น การเพิ่มตัวนับหรือการส่งการแจ้งเตือน ถือเป็นการละเมิดความหมายของ HTTP และทำลายโครงสร้างพื้นฐานการแคช
POST สร้างทรัพยากรใหม่ แตกต่างจาก GET, POST ไม่ปลอดภัยและไม่เป็น Idempotent การส่งคำขอ POST ที่เหมือนกันหลายครั้งมักจะสร้างทรัพยากรหลายรายการ ลักษณะที่ไม่เป็น Idempotent นี้ต้องการการจัดการข้อผิดพลาดเครือข่ายอย่างระมัดระวัง—ไคลเอ็นต์ไม่สามารถลองส่งคำขอ POST ซ้ำได้อย่างปลอดภัยโดยไม่มีกลไกเพิ่มเติม
PUT แทนที่ทรัพยากรทั้งหมดด้วยข้อมูลใหม่ เป็น Idempotent—ให้ผลลัพธ์สุดท้ายเหมือนเดิม ความเป็น Idempotent นี้ช่วยให้สามารถลองใหม่ได้อย่างปลอดภัยเมื่อเกิดข้อผิดพลาดเครือข่าย การ PUT ไปยัง /users/123 ด้วยออบเจกต์ผู้ใช้ที่สมบูรณ์จะแทนที่ผู้ใช้นั้นทั้งหมด
PATCH ทำการอัปเดตบางส่วน เฉพาะฟิลด์ที่ระบุเท่านั้นที่จะเปลี่ยนแปลง ส่วนอื่นๆ ยังคงไม่ถูกแตะต้อง การนำ PATCH ไปใช้แตกต่างกันไป—บางแนวทางเป็น Idempotent (แทนที่ฟิลด์เฉพาะ) ในขณะที่บางแนวทางไม่ใช่ (เพิ่มตัวนับ) การจัดทำเอกสารพฤติกรรมนี้อย่างชัดเจนช่วยให้ไคลเอ็นต์จัดการการลองใหม่ได้อย่างเหมาะสม
DELETE ลบทรัพยากร เป็น Idempotent เนื่องจากผลลัพธ์ยังคงสอดคล้องกัน: ทรัพยากรหยุดอยู่ การเรียก DELETE ครั้งแรกจะลบทรัพยากร; การเรียกครั้งถัดไปจะไม่พบอะไรให้ลบ แต่ก็บรรลุสถานะสุดท้ายเดียวกัน
รหัสสถานะและการสื่อสารข้อผิดพลาด
รหัสสถานะ HTTP ให้ข้อเสนอแนะทันทีเกี่ยวกับผลลัพธ์ของคำขอ การใช้รหัสเหล่านี้อย่างสอดคล้องกันช่วยให้นักพัฒนาวินิจฉัยปัญหาได้อย่างรวดเร็วโดยไม่ต้องแยกวิเคราะห์เนื้อหาการตอบสนอง
| หมวดหมู่ | ช่วง | ความหมาย |
|---|---|---|
| 2xx | 200-299 | สำเร็จ |
| 4xx | 400-499 | ข้อผิดพลาดจากไคลเอ็นต์ |
| 5xx | 500-599 | ข้อผิดพลาดจากเซิร์ฟเวอร์ |
สถานะ 200 OK แสดงถึงคำขอ GET ที่สำเร็จ คำขอ POST ที่สร้างทรัพยากรควรคืนค่า 201 Created ซึ่งมักจะรวมส่วนหัว Location ที่ชี้ไปยังทรัพยากรใหม่ การดำเนินการ DELETE และ PUT บางอย่างอาจคืนค่า 204 No Content เมื่อเนื้อหาการตอบกลับว่างเปล่าโดยเจตนา
ข้อผิดพลาดของไคลเอ็นต์ (4xx) บ่งชี้ถึงปัญหาที่ผู้เรียกสามารถแก้ไขได้ 400 Bad Request บ่งชี้ถึง JSON ที่มีรูปแบบไม่ถูกต้องหรือฟิลด์ที่จำเป็นขาดหายไป 401 Unauthorized หมายถึงจำเป็นต้องมีการตรวจสอบสิทธิ์หรือล้มเหลว 403 Forbidden บ่งชี้ว่าผู้ใช้ที่ตรวจสอบสิทธิ์แล้วไม่มีสิทธิ์ 404 Not Found พูดในตัวมันเอง—แม้ว่าบางครั้งจะใช้เพื่อซ่อนทรัพยากรที่มีอยู่แต่ไม่สามารถเข้าถึงได้ ด้วยเหตุผลด้านความปลอดภัย
ข้อผิดพลาดของเซิร์ฟเวอร์ (5xx) บ่งชี้ถึงปัญหาที่ไคลเอ็นต์ไม่สามารถแก้ไขได้ สิ่งเหล่านี้ต้องมีการตรวจสอบและแก้ไขที่ฝั่งเซิร์ฟเวอร์ การคืนค่าปัญหาที่เกิดจากไคลเอ็นต์ทำให้การแก้ไขปัญหาเป็นเรื่องที่สับสน
การตอบกลับข้อผิดพลาดควรรวมข้อมูลที่มีโครงสร้างและสามารถดำเนินการได้:
{
"error": "VALIDATION_FAILED",
"message": "The request body contains invalid data",
"details": [
{
"field": "email",
"issue": "Invalid email format"
},
{
"field": "password",
"issue": "Must be at least 8 characters"
}
]
}
โครงสร้างนี้มีรหัสข้อผิดพลาดสำหรับการจัดการโปรแกรม ข้อความที่มนุษย์อ่านได้ และรายละเอียดเฉพาะเกี่ยวกับสิ่งที่ผิดพลาด ไคลเอ็นต์สามารถแยกวิเคราะห์ข้อมูลนี้เพื่อแสดงข้อผิดพลาดที่เป็นประโยชน์แก่ผู้ใช้
กลยุทธ์การกำหนดเวอร์ชันสำหรับการพัฒนา
API มีการพัฒนา ฟีเจอร์ใหม่ๆ ปรากฏขึ้น โครงสร้างข้อมูลเปลี่ยนแปลง และบางครั้งการแก้ไขที่ส่งผลกระทบก็กลายเป็นสิ่งจำเป็น การกำหนดเวอร์ชัน ช่วยให้การพัฒนาเหล่านี้เกิดขึ้นได้โดยไม่กระทบกับไคลเอ็นต์ที่มีอยู่
การกำหนดเวอร์ชันด้วย URI จะใส่เวอร์ชันไว้ในพาธ URL:
GET /v1/users
GET /v2/users
แนวทางนี้ให้ความชัดเจนและความเรียบง่าย นักพัฒนาสามารถดูได้อย่างรวดเร็วว่าพวกเขากำลังใช้เวอร์ชันใด การทดสอบและการดีบักบนเบราว์เซอร์กลายเป็นเรื่องง่าย API สาธารณะส่วนใหญ่ใช้กลยุทธ์นี้เนื่องจากความโปร่งใส
การกำหนดเวอร์ชันตามส่วนหัวจะย้ายข้อมูลเวอร์ชันไปยังส่วนหัว HTTP:
GET /users
Accept: application/vnd.myapi.v2+json
URL ยังคงสะอาดและเสถียร อย่างไรก็ตาม แนวทางนี้ค้นพบได้ยากกว่า—นักพัฒนาไม่สามารถเห็นเวอร์ชันในแถบที่อยู่ของเบราว์เซอร์ได้ การทดสอบต้องใช้เครื่องมือที่รองรับส่วนหัวที่กำหนดเอง
การกำหนดเวอร์ชันด้วยพารามิเตอร์การสอบถามจะใส่ข้อมูลเวอร์ชันในสตริงการสอบถาม:
GET /users?version=2
แนวทางนี้ผสมผสานการกำหนดเวอร์ชันกับการกรองทรัพยากร ซึ่งบางคนถือว่าไม่บริสุทธิ์ทางสถาปัตยกรรม อย่างไรก็ตาม ยังคงใช้งานและทดสอบได้ง่าย
กลยุทธ์ที่เฉพาะเจาะจงนั้นมีความสำคัญน้อยกว่าความสอดคล้องและการสื่อสารที่ชัดเจน เมื่อเลือกแนวทางการกำหนดเวอร์ชันแล้ว ควรกำหนดวิธีการทำงานของเวอร์ชันและสิ่งที่แต่ละเวอร์ชันเปลี่ยนแปลงไปอย่างสม่ำเสมอ
ข้อควรพิจารณาด้านความปลอดภัยในการออกแบบ
ช่องโหว่ด้านความปลอดภัยใน API อาจเปิดเผยข้อมูลที่ละเอียดอ่อน เปิดใช้งานการกระทำที่ไม่ได้รับอนุญาต และสร้างความเสียหายต่อชื่อเสียงขององค์กร การจัดการความปลอดภัยระหว่างการออกแบบช่วยป้องกันการแก้ไขเพิ่มเติมที่มีค่าใช้จ่ายสูงในภายหลัง
การตรวจสอบสิทธิ์ (Authentication) ตรวจสอบตัวตน—พิสูจน์ว่าใครเป็นผู้ส่งคำขอ แนวทางทั่วไปรวมถึง API keys สำหรับการสื่อสารระหว่างเซิร์ฟเวอร์ และ OAuth 2.0 สำหรับการเข้าถึงที่ผู้ใช้มอบสิทธิ์ให้ JSON Web Tokens (JWT) ให้การตรวจสอบสิทธิ์แบบไร้สถานะ โดยเข้ารหัสตัวตนผู้ใช้และสิทธิ์ในโทเค็นที่ลงชื่อแล้ว
การอนุญาต (Authorization) กำหนดสิทธิ์—สิ่งที่ตัวตนที่ตรวจสอบสิทธิ์แล้วสามารถทำได้ Role-Based Access Control (RBAC) กำหนดสิทธิ์ให้กับบทบาท จากนั้นกำหนดบทบาทให้กับผู้ใช้ ลูกค้าอาจเข้าถึงได้เฉพาะคำสั่งซื้อของตนเองเท่านั้น ในขณะที่พนักงานฝ่ายสนับสนุนสามารถดูคำสั่งซื้อใดก็ได้
การรับส่งข้อมูล API ทั้งหมดควรกระทำผ่าน HTTPS HTTP ที่ไม่ได้เข้ารหัสจะเปิดเผยข้อมูลรับรอง โทเค็น และข้อมูลที่ละเอียดอ่อนแก่ทุกคนบนเครือข่าย ข้อกำหนดนี้ควรถูกบังคับใช้ในระดับโครงสร้างพื้นฐาน โดยการเปลี่ยนเส้นทางคำขอ HTTP ไปยัง HTTPS
การจำกัดอัตรา (Rate limiting) ช่วยปกป้อง API จากการใช้งานในทางที่ผิด ไม่ว่าจะเป็นด้วยเจตนาร้ายหรือโดยไม่ได้ตั้งใจ การจำกัดสามารถใช้กับผู้ใช้แต่ละคน, IP แต่ละรายการ หรือ API-key แต่ละรายการ เมื่อเกินขีดจำกัด API จะคืนค่า 429 Too Many Requests พร้อมส่วนหัวที่ระบุว่าไคลเอ็นต์สามารถลองใหม่ได้เมื่อใด:
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1699887600
การตรวจสอบความถูกต้องของข้อมูลป้อนเข้า (Input validation) ป้องกันการโจมตีแบบ Injection และความเสียหายของข้อมูล ทุกช่องป้อนข้อมูลควรได้รับการตรวจสอบเทียบกับรูปแบบ ความยาว และช่วงที่คาดไว้ ข้อมูลที่เป็นอันตรายควรถุกปฏิเสธพร้อมข้อความแสดงข้อผิดพลาดที่ชัดเจน—โดยไม่เปิดเผยรายละเอียดการใช้งานภายใน
การจัดการชุดข้อมูลขนาดใหญ่ด้วยการแบ่งหน้า (Pagination)
การคืนค่าข้อมูลหลายพันรายการในการตอบกลับครั้งเดียวสร้างภาระให้กับทั้งเซิร์ฟเวอร์และไคลเอ็นต์ การแบ่งหน้าช่วยแบ่งชุดข้อมูลขนาดใหญ่เป็นส่วนๆ ที่จัดการได้ง่าย
การแบ่งหน้าตาม Offset ใช้พารามิเตอร์ skip และ limit:
GET /products?GET /products?offset=20&limit=20
แนวทางนี้ใช้งานง่ายและช่วยให้สามารถข้ามไปยังหน้าใดก็ได้ อย่างไรก็ตาม ประสิทธิภาพไม่ดีเมื่อใช้ offset ขนาดใหญ่ และอาจแสดงบันทึกที่ซ้ำกันหรือหายไปหากข้อมูลเปลี่ยนแปลงระหว่างคำขอ
การแบ่งหน้าตาม Cursor ใช้โทเค็นทึบแสงที่ระบุตำแหน่ง:
GET /products?limit=20
{
"data": [...],
"next_cursor": "eyJpZCI6MjB9"
}
GET /products?cursor=eyJpZCI6MjB9&limit=20
การแบ่งหน้าด้วย Cursor จัดการข้อมูลแบบเรียลไทม์ได้อย่างราบรื่น—บันทึกใหม่ไม่ทำให้เกิดการซ้ำซ้อน บันทึกที่ถูกลบไม่ทำให้เกิดช่องว่าง อย่างไรก็ตาม ไม่รองรับการข้ามไปยังหน้าใดก็ได้
การเลือกขึ้นอยู่กับกรณีการใช้งาน ชุดข้อมูลแบบสถิติที่มีการเรียกดูเป็นครั้งคราวเหมาะกับการแบ่งหน้าแบบ offset ส่วนฟีดแบบเรียลไทม์ที่มีการบริโภคตามลำดับจะได้รับประโยชน์จากการแบ่งหน้าแบบ cursor
เอกสารประกอบในฐานะสิ่งประดิษฐ์ทางการออกแบบ
เอกสารประกอบ ทำหน้าที่เป็นส่วนต่อประสานหลักระหว่าง API และผู้บริโภค เอกสารประกอบที่ไม่ดีจะทำให้นักพัฒนาถอยห่าง ไม่ว่า API พื้นฐานจะได้รับการออกแบบมาดีแค่ไหนก็ตาม
เอกสารประกอบ API สมัยใหม่มักใช้ OpenAPI Specification (เดิมคือ Swagger) รูปแบบที่เครื่องอ่านได้นี้อธิบายถึงปลายทาง พารามิเตอร์ เนื้อหาคำขอ และการตอบกลับ เครื่องมือสามารถสร้างเอกสารประกอบแบบโต้ตอบ ไลบรารีไคลเอ็นต์ และ Server stubs จากคำจำกัดความของ OpenAPI
เอกสารประกอบควรรวมถึง:
คำอธิบายที่ชัดเจนว่า API ทำอะไรและใครควรใช้ ข้อกำหนดการตรวจสอบสิทธิ์พร้อมตัวอย่างการขอและใช้งานข้อมูลรับรอง ปลายทางทุกจุดพร้อม URL, เมธอด HTTP, พารามิเตอร์ และรูปแบบเนื้อหาคำขอ รูปแบบการตอบกลับรวมถึงตัวอย่างความสำเร็จและข้อผิดพลาด กรณีการใช้งานทั่วไปพร้อมตัวอย่างโค้ดในภาษาที่เป็นที่นิยม
เอกสารประกอบแบบโต้ตอบที่อนุญาตให้ทำการเรียก API สดช่วยลดความยุ่งยากได้อย่างมาก นักพัฒนาสามารถทดลองได้โดยตรงในเบราว์เซอร์ของตนโดยไม่ต้องตั้งค่าสภาพแวดล้อมการทดสอบแยกต่างหาก
ข้อผิดพลาดทั่วไปในการออกแบบที่ควรหลีกเลี่ยง
ข้อผิดพลาดที่เกิดขึ้นซ้ำๆ หลายประการสร้างปัญหาในการออกแบบ API ทำให้เกิดความยุ่งยากสำหรับนักพัฒนาและภาระในการบำรุงรักษาสำหรับทีม ปลายทางเช่น /getUsers หรือ /createOrder ผสมผสานความหมายของการกระทำกับการระบุทรัพยากร แทนที่จะเป็นเช่นนั้น ให้ใช้เมธอด HTTP กับ URL ทรัพยากร: GET /users หรือ POST /orders
การละเลยความหมายของเมธอด HTTP ทำให้เกิดบั๊กที่ละเอียดอ่อน ปลายทาง GET ที่แก้ไขข้อมูลจะทำลายการแคชและสามารถกระตุ้นผลข้างเคียงที่ไม่พึงประสงค์เมื่อเบราว์เซอร์ดึงข้อมูลล่วงหน้าหรือโปรแกรมรวบรวมข้อมูลจัดทำดัชนี API เบราว์เซอร์และพร็อกซีอาจแคชการตอบกลับ GET ทำให้ส่งคืนข้อมูลที่ล้าสมัย
การจัดการข้อผิดพลาดที่ไม่สอดคล้องกันทำให้นักพัฒนาหงุดหงิด การส่งคืนโครงสร้างข้อผิดพลาดที่แตกต่างกันสำหรับปลายทางที่แตกต่างกัน หรือการใช้ HTTP 200 ที่มีรายละเอียดข้อผิดพลาดในเนื้อหา ทำให้ไคลเอ็นต์ต้องจัดการเส้นทางการแยกวิเคราะห์หลายเส้นทาง โครงสร้างข้อผิดพลาดที่สอดคล้องกันพร้อมรหัสสถานะที่เหมาะสมช่วยให้การจัดการข้อผิดพลาดราบรื่นขึ้น
API ที่มีลักษณะเป็น "Chatty" ต้องการการเรียกไปกลับหลายครั้งสำหรับการดำเนินการทั่วไป การต้องเรียกแยกกันเพื่อดึงผู้ใช้ จากนั้นโปรไฟล์ของพวกเขา จากนั้นการตั้งค่าของพวกเขา จากนั้นการตั้งค่าต่างๆ สร้างความล่าช้าโดยไม่จำเป็น การออกแบบปลายทางที่คืนค่าข้อมูลที่เกี่ยวข้องในการตอบกลับครั้งเดียวช่วยปรับปรุงประสิทธิภาพ
การดึงข้อมูลมากเกินไปทำให้สิ้นเปลืองแบนด์วิดท์ การคืนค่าออบเจกต์ผู้ใช้ที่สมบูรณ์เมื่อต้องการเพียงชื่อเท่านั้น จะสร้างภาระให้ไคลเอ็นต์ในการแยกวิเคราะห์และทิ้งข้อมูลที่ไม่จำเป็น การรองรับการเลือกฟิลด์ผ่านพารามิเตอร์การสอบถามช่วยให้ไคลเอ็นต์สามารถร้องขอเฉพาะฟิลด์ที่ต้องการ:
GET /users?fields=id,name,email
แนวทาง Design-First กับ Code-First
การอภิปรายระหว่างการออกแบบ API ก่อนกับการสร้างการออกแบบจากโค้ด สัมผัสกับปรัชญาการพัฒนาพื้นฐาน
แนวทาง Design-first สร้างข้อกำหนด API ก่อนการนำไปใช้งาน คำจำกัดความของ OpenAPI ทำหน้าที่เป็นสัญญาที่ผู้มีส่วนได้ส่วนเสียทั้งหมดตรวจสอบและอนุมัติ Mock server ช่วยให้ทีมส่วนหน้าและส่วนหลังทำงานพร้อมกัน การนำไปใช้งานดำเนินไปพร้อมเป้าหมายที่ชัดเจน
แนวทาง Code-first สร้างข้อกำหนด API จากโค้ดที่นำไปใช้งาน สิ่งนี้รับประกันว่าเอกสารประกอบตรงกับความเป็นจริง—เพราะโค้ดสร้างเอกสารประกอบ อย่างไรก็ตาม มีความเสี่ยงที่จะเปิดเผยรายละเอียดการใช้งานมากกว่าการออกแบบเพื่อตอบสนองความต้องการของผู้บริโภค
องค์กรที่มีการกำกับดูแล API ที่แข็งแกร่งมักถูกกดดันให้ส่งมอบงานอย่างรวดเร็ว บางครั้งจึงเลือกใช้แนวทาง code-first แนวทางแบบผสมผสาน—ออกแบบ API ใหม่ก่อน แล้วสร้างข้อกำหนดสำหรับ API ที่มีอยู่—จะช่วยสร้างสมดุลระหว่างความกังวลทั้งสอง
เส้นทางข้างหน้า
การออกแบบ API เป็นพื้นฐานที่หล่อหลอมวิธีการทำงานร่วมกันของระบบ การตัดสินใจที่เกิดขึ้นระหว่างการออกแบบจะสะท้อนไปตลอดหลายปีของการบำรุงรักษา การผสานรวม และการพัฒนา การลงทุนเวลาในการออกแบบอย่างรอบคอบจะให้ผลตอบแทนในแง่ของความพึงพอใจของนักพัฒนา ความน่าเชื่อถือของระบบ และความคล่องตัวขององค์กร
หลักการที่กล่าวมาข้างต้น—ความสอดคล้อง ความเรียบง่าย ความปลอดภัย การสื่อสารข้อผิดพลาดที่ชัดเจน เอกสารประกอบที่ครอบคลุม—เป็นรากฐาน การประยุกต์ใช้จะแตกต่างกันไปตามบริบท ทีม และข้อกำหนด ไม่มีแนวทางใดที่เหมาะกับทุกสถานการณ์
สิ่งที่ยังคงไม่เปลี่ยนแปลงคือการมุ่งเน้นไปที่ประสบการณ์ของนักพัฒนา API มีอยู่เพื่อถูกใช้งาน ทางเลือกในการออกแบบที่ให้ความสำคัญกับความชัดเจน ความสามารถในการคาดเดา และความง่ายในการใช้งาน จะสร้างอินเทอร์เฟซที่นักพัฒนาให้การยอมรับมากกว่าที่จะต้องทนใช้
