Một API (Application Programming Interface – Giao diện lập trình ứng dụng) được thiết kế kém có thể dẫn đến code khó bảo trì, người dùng (client) cảm thấy bối rối, rủi ro bảo mật, và nghẽn hiệu suất. Ngược lại, một API được thiết kế tốt sẽ có đặc điểm: dễ đoán, nhất quán, mở rộng được và thân thiện với lập trình viên.
Dưới đây là 5 yếu tố quan trọng mà bất kỳ lập trình viên nào cũng nên cân nhắc khi thiết kế API:
1 – Giao diện (Interface)
Về cốt lõi, một API chính là một giao diện giữa các hệ thống — một "hợp đồng" mô tả cách một client có thể tương tác với một dịch vụ. Giao diện này gồm:
-
Resources (Tài nguyên): Những thực thể cốt lõi bạn làm việc với là gì? (Ví dụ: người dùng, sản phẩm, đơn hàng)
-
Endpoints (Điểm truy cập API): Client sẽ tương tác với các tài nguyên này ra sao? (Ví dụ:
GET /users
,POST /orders
) -
Request and Response Formats (Định dạng yêu cầu và phản hồi): Bạn sử dụng định dạng nào? JSON hay XML? Có tuân theo quy ước đặt tên và cấu trúc dữ liệu thống nhất không?
Một giao diện API tốt sẽ:
-
Tuân theo quy ước đặt tên rõ ràng (danh từ cho tài nguyên, động từ cho hành động)
-
Sử dụng cấu trúc đường dẫn (URI) có thể đoán trước (ví dụ:
/users/123/orders
) -
Trả về mã trạng thái HTTP rõ ràng và nhất quán (ví dụ: 200 OK, 201 Created, 404 Not Found)
📌 Lời khuyên: Hãy xem API như một sản phẩm. Dù chỉ dùng nội bộ, người khác vẫn sẽ sử dụng nó — hãy khiến trải nghiệm của họ trở nên trực quan.
2 – Các kiểu thiết kế API (API Paradigms)
Không có một kiểu API nào phù hợp với mọi trường hợp. Lựa chọn đúng tùy thuộc vào mục đích sử dụng, yêu cầu hiệu suất và mức độ linh hoạt của client.
Một số kiểu phổ biến:
-
REST (Representational State Transfer): Dựa trên tài nguyên, không lưu trạng thái (stateless), được sử dụng rộng rãi. Phù hợp với thao tác CRUD (Create, Read, Update, Delete), đơn giản và dễ hiểu.
-
GraphQL: Kiểu API cho phép client tự định nghĩa dữ liệu muốn lấy về. Giúp tránh việc lấy quá nhiều (over-fetching) hoặc quá ít (under-fetching) dữ liệu.
-
gRPC: Giao thức gọi hàm từ xa (Remote Procedure Call) dạng nhị phân hiệu suất cao do Google phát triển. Phù hợp cho hệ thống nội bộ có lượng trao đổi lớn.
Ưu – nhược điểm:
Kiểu API | Ưu điểm | Nhược điểm |
---|---|---|
REST | Dễ hiểu, dễ cache | Ít linh hoạt hơn |
GraphQL | Rất linh hoạt | Khó bảo mật hơn |
gRPC | Rất nhanh | Không hỗ trợ trực tiếp trong trình duyệt |
🎯 Lời khuyên: Chọn kiểu thiết kế phù hợp với mục tiêu. Đừng ép buộc dùng REST chỉ vì nó phổ biến.
3 – Mô hình hóa mối quan hệ (Modeling Relationships)
Trong hệ thống thực tế, các thực thể thường có mối quan hệ với nhau:
-
Một người dùng có nhiều đơn hàng
-
Một bài viết có bình luận
-
Một sản phẩm có đánh giá
API của bạn nên thể hiện những mối quan hệ này một cách rõ ràng và dễ truy cập.
Ví dụ, thay vì:
Hãy dùng:
Điều này làm rõ cấu trúc phân cấp và quan hệ giữa tài nguyên. Nó cũng giúp endpoint dễ khám phá và mang lại ý nghĩa rõ ràng hơn.
Với GraphQL, mối quan hệ được thể hiện rất tự nhiên:
Giữ một cấu trúc rõ ràng và logic trong cách thể hiện quan hệ giúp API dễ sử dụng và dễ duy trì.
4 – Quản lý phiên bản (API Versioning)
API sẽ thay đổi theo thời gian. Bạn thêm tính năng, sửa lỗi, thay đổi mô hình dữ liệu. Nhưng các client hiện tại vẫn có thể đang sử dụng phiên bản cũ.
Vì vậy, quản lý phiên bản (versioning) là điều rất quan trọng.
Các cách phổ biến:
-
URI versioning:
/v1/users
,/v2/users
-
Header versioning:
Accept: application/vnd.myapi.v2+json
-
Query param versioning:
/users?version=2
🎯 Mục tiêu là:
-
Tránh phá vỡ các client cũ
-
Thông báo rõ ràng rằng có thay đổi
-
Cho phép hỗ trợ song song cả client cũ và mới
📌 Lưu ý: Chỉ nên nâng version khi có thay đổi gây ảnh hưởng (breaking change). Nếu có thể, hãy phát triển API theo hướng mở rộng, không làm gián đoạn.
5 – Giới hạn tốc độ (Rate Limiting)
Nếu không có giới hạn, một client có thể gửi hàng ngàn request mỗi giây và khiến hệ thống quá tải — dù là do lỗi hay tấn công có chủ đích.
Rate limiting giúp kiểm soát số lượng request mà một client có thể gửi trong một khoảng thời gian, ví dụ: 100 request/phút.
Điều này giúp:
-
Bảo vệ hệ thống backend
-
Đảm bảo công bằng cho tất cả người dùng
Các kỹ thuật giới hạn phổ biến:
-
Fixed window (cửa sổ cố định): Đếm số lượng request trong từng khoảng thời gian nhất định.
-
Sliding window (cửa sổ trượt): Giúp lưu lượng truy cập ổn định hơn.
-
Token bucket: Cho phép "vượt ngưỡng" trong thời gian ngắn, nhưng vẫn đảm bảo tổng thể nằm trong giới hạn.
Thông thường, hệ thống sẽ gửi thông tin về giới hạn bằng các HTTP Header:
Bạn có thể áp dụng giới hạn khác nhau tùy theo:
-
API key hoặc access token
-
Vai trò người dùng (miễn phí vs trả phí)
-
Loại endpoint (nặng vs nhẹ)
📌 Mẹo chuyên sâu: Hãy luôn tài liệu hóa (document) rõ ràng giới hạn của API và gửi kèm trong phản hồi để người dùng nắm được.