Một số quy tắc thiết kế API

Một số quy tắc thiết kế API

Tin ngắn hàng ngày dành cho bạn
  • Rust sinh ra để tái định nghĩa nhiều thứ. Trong đó chắc phải kể đến JavaScript. Từ đầu năm đến giờ các công cụ làm từ Rust mà để cho JavaScript dùng đếm sương sương cũng vài ba cái rồi. Mới đây nhất là Oxc.

    Oxc là một công cụ phân tích cú pháp (parser), kiểm tra lỗi (lint), định dạng (formatter), chuyển đổi (transformer), minifier... tất cả đều được viết bằng Rust, trong một công cụ duy nhất.

    Mặc dù vẫn đang trong quá trình xây dựng nhưng thử nhìn điểm hiệu năng của nó so với swc hoặc eslint mà xem 🫣

    » Xem thêm
  • Mấy hôm nay, à mà cũng không hẳn, do sự kiện WWDC vừa rồi nên Apple lại bị dân cư mạng mang ra bàn tán rằng rốt cục thì các tính năng AI của họ đang ở đâu? Trong khi các hãng khác đang lao mình vào việc mang AI lên thiết bị, phần mềm của họ thì Apple lại đang có vẻ... không quan tâm lắm.

    Thậm chí mới đây các nhà nghiên cứu của Apple cho rằng các mô hình LLM sẽ "sụp đổ hoàn toàn về độ chính xác" khi được đưa ra các vấn đề cực kỳ phức tạp. Chỉ ra rằng suy luận chỉ là huyễn hoặc thì ngay lập tức đã có nhiều bài phản bác nghiên cứu này. Một lần nữa cho thấy rằng Apple đang suy nghĩ điều gì với AI trên thiết bị của họ?

    Mình thì nghĩ đơn giản thôi, Apple có vẻ đang gặp khó khăn với việc tạo ra AI cho riêng họ. Tức là khó khăn ngay từ đoạn thu thập dữ liệu để đào tạo rồi. Họ luôn tỏ ra tôn trọng quyền riêng tư của người dùng nên chẳng lẽ lại lên mạng đi xào nấu dữ liệu ở khắp nơi, hoặc "chôm" dữ liệu dưới máy người dùng lên? Chắc chắn, họ cũng không muốn cung cấp thêm dữ liệu người dùng cho các bên thứ 3 như OpenAI.

    Nhưng nhờ những khó khăn này biết đâu họ lại tìm ra được hướng đi mới. Ai cũng chọn phần dễ thì gian khổ để phần cho ai 😁. À mình không phải là "fan" của Apple, chỉ là thấy cái nào phù hợp thì dùng thôi 🤓

    » Xem thêm
  • Người "nhạy cảm" với markdown đó là khi thấy một thư viện tạo khung soạn thảo mới là nhảy ngay vào xem nó có gì mới. Milkdown/milkdown là một ví dụ.

    Xem thử thì thấy ổn phết mọi người ạ. Vài nữa thử tích hợp vào opennotas xem sao. Mang tiếng là ứng dụng ghi chú hỗ trợ markdown cơ mà cái thư viện tiptap nó không chịu làm thêm phần hỗ trợ markdown 😩. Dùng thư viện ngoài thì vẫn chưa ngon cho lắm.

    » Xem thêm

Vấn đề

Khi viết chương trình, chúng ta có các Design Pattern nên hoặc thậm chí cần được tuân theo để giúp cho mọi người trong nhóm có thể hiểu và phối hợp với nhau một cách nhịp nhàng. Các "mẫu thiết kế" là minh chứng rõ nhất cho việc đọc hiểu dễ hơn khi con người chúng ta cùng chung một lối suy nghĩ.

Design API cũng vậy, việc tạo ra hàng tá endpoint trong một khoảng thời gian là khá dễ nhưng làm sao để duy trì được sự thống nhất trong suốt quá trình phát triển mới là điều khó. Dự án phát triển theo năm tháng, con người cũng thay đổi, càng có nhiều bộ óc tham gia vào quá trình, càng có nhiều tính cách được bộc phát qua những dòng code.

Thực tê, Design API phụ thuộc vào tính sáng tạo của từng cá nhân, tổ chức. Nếu một nhóm không quá khắt khe với vấn đề đặt tên cho một endpoint thì thế giới này là của bạn, hãy tự do sáng tạo dựa trên những gì có thể nghĩ ra được. Ngược lại, có những tổ chức lại đưa ra những quy định ngặt nghèo trong quá trình này, buộc chúng ta phải tuân theo. Nhưng dù là thế nào đi nữa, mục đích cuối cùng của việc đó vẫn là làm sao để đại đa số lập trình viên nhìn vào đều có thể hiểu hoặc biết cách để tìm kiếm thứ mà họ cần.

Tôi là một người thích sự sáng tạo, nhưng không nên phá cách. Có những thứ mình vẫn cần tuân theo để đảm bảo được sự minh bạch của API. Bài viết này hôm nay, tôi sẽ trình bày một số quy tắc trong quá trình Design API mà rất nhiều lập trình viên trên thế giới đang áp dụng. Nếu không tin, sau khi đọc xong bài viết này, hãy thử "vọc vạch" một bộ API của bất kỳ bên thứ 3 nào đó đang cung cấp để xem họ đang làm như thế nào.

Một lần nữa, các quy tắc nêu ra dưới đây chỉ để tham khảo và không bắt buộc ai phải làm theo. Nếu bạn nhận ra được lợi ích từ việc tuân theo nguyên tắc, tôi tin rằng đây là một điều không nên bỏ qua. Không dài dòng nữa, vào việc thôi!

Một số quy tắc

Đầu tiên, hãy làm rõ một số khái niệm liên quan đến việc thiết kế API.

Chúng ta có resource, đại diện cho "tài nguyên" muốn truy cập hoặc thực hiện một thao tác. Khi gọi đến một endpoint, dữ liệu được trả về, nó là danh sách bài viết, chi tiết bài viết… gọi chung là resource. Bên cạnh đó, trong resource thường có các thuộc tính (attributes), chúng là một thành phần của resource hoặc được tính toán dựa trên resource.

Một "bộ sưu tập" hay Collections là tập hợp của các resource, thông thường các resource giống nhau được xếp chung vào một Collections. Ví dụ đối với một tài nguyên là "Users", chúng ta có tập hợp các thao tác với người dùng như là thêm, sửa, xóa… gọi là Collections.

URLs thì rõ rồi, đường dẫn đến resource của bạn. Ví dụ /articles để trỏ vào danh sách bài viết.

Quy tắc về đường dẫn (path)

Xác định bộ sưu tập cho tài nguyên, ví dụ /articles cho các bài viết, /comments cho các bình luận và luôn sử dụng danh từ số nhiều.

Sử dụng "kebab-case" cho mọi thứ trong đường dẫn URLs, "camelCase" cho tham số trong truy vấn. Ví dụ /special-articles?isHighlight=true.

Sử dụng "mã định danh" như ID của resource để thao tác với một tài nguyên chỉ định. Ví dụ: /articles/nodejs-la-gi để tương tác với bài viết có URL "nodejs-la-gi".

Tránh sử dụng đường dẫn có chứa thuộc tính của resource hoặc là các hành động đối với resource, nó sẽ gây ra nhiều rắc rối cũng như phức tạp hóa đường dẫn sau này. Ví dụ: không nên /articles/nodejs-la-gi/summary hoặc /articles/nodejs-la-gi/reset-view, hãy thử chuyển thuộc tính vào parameters hoặc trong request body, ví dụ /articles/nodejs-la-gi?summary=true.

Nên xác định tiền tố cho phiên bản API, ví dụ /v1/articles để trỏ đến phiên bản 1 của API. Nếu sau này nâng cấp API, chúng ta có thể mở rộng thêm /v2, /v3… mà hạn chế ảnh hưởng đến các phiên bản trước đó.

Quy tắc về phương thức

Có 5 phương thức HTTP phổ biến mà chắc hẳn ai cũng nghe qua.

GET: Để lấy một tài nguyên.
POST: Để tạo tài nguyên mới.
PUT: Để cập nhật các tài nguyên hiện có.
PATCH: Để cập nhật các tài nguyên hiện có, nhưng chỉ cập nhật các trường được cung cấp, để yên những trường khác.
DELETE: Để xóa các tài nguyên hiện có.

Kết hợp với quy tắc về đường dẫn, các phương thức HTTP góp phần làm rõ thêm hành động bạn đang muốn tương tác với tài nguyên là gì. Ví dụ:

GET /articles - lấy danh sách tất cả bài biết.
GET /articles/nodejs-la-gi - lấy chi tiết bài viết có URL nodejs-la-gi.
POST /articles - tạo mới một bài viết.
DELETE /articles - xóa bài viết.

Quy tắc về response status code

HTTP response status code là những con số cho biết liệu một yêu cầu HTTP có được hoàn thành hay là không.

Có rất nhiều status code nhưng dưới đây là một vài con số chúng ta thường hay gặp:

200 OK: thành công.
201 Created: thường được trả về khi API vừa tạo một tài nguyên mới thành công.
204 No Content: thao tác thành công nhưng không có gì được trả về, ví dụ như thao tác DELETE một tài nguyên đã có.
400 Bad Request: báo lỗi khi một yêu cầu không hợp lệ, có thể là hành vi gửi lên dữ liệu không hợp lệ cho nên cần phải từ chối xử lý.
401 Unauthorized: lỗi khi yêu cầu này cần xác thực thông tin hợp lệ trước khi hành động, ví dụ như chưa đăng nhập vào hệ thống.
403 Forbidden: lỗi khi không có quyền thực hiện chức năng này.
404 Not Found: lỗi không tìm thấy tài nguyên hoặc hành động.
500 Internal Server Error: một lỗi "không xác định" từ máy chủ, có thể do sự cố ngoài ý muốn như lỗi phần cứng, phần mềm, mạng…

Ngoài ra, bạn đọc có thể tham khảo thêm mã lỗi khác tại HTTP response status codes - Mozilla. Việc tuân thủ status code giúp đạt được sự thống nhất trong quá trình phát triển, cũng như cho các bên tích hợp API.

Quy tắc về response body

Giữ cho response body của bạn được xuyên suốt từ đầu đến cuối. Ví dụ một phản hồi thành công bao gồm mã phản hồi, thông điệp và dữ liệu trả về.

{
  "status": 200,  
  "message": "OK",  
  "data": {
    "id": 1,  
    "name": "John Doe",  
    "email": "[email protected]"
  }
}

Nếu là thông báo lỗi, hãy kèm theo mã lỗi và thông điệp lỗi.

{
  "code": 400,  
  "message": "Bad Request"
}

Giữ thông báo lỗi chung nhất có thể để hạn chế việc làm lộ dữ liệu hoặc thông tin quan trọng khác.

Ngoài ra, có một vài quy tắc khác trong việc thiết kế API như:

Luôn phân trang cho các yêu cầu đến tài nguyên dạng danh sách, ví dụ /articles?limit=10&offset=0 hoặc /articles?page=1&limit=10… Nếu có thể, trả về thêm tổng số resource có trong danh sách đó. Các tài nguyên dạng danh sách cũng có thể cần được sắp xếp theo một thứ tự nào đó, ví dụ /articles?sort=createdAt:desc

Tài nguyên chi tiết thông thường trả về hết thuộc tính có thể có, nhưng đó không phải lúc nào cũng cần, có thể hỗ trợ cần lấy những thuộc tính nào thông qua lọc, ví dụ /articles?field=url,title,content,createdAt

Tham khảo:

API design.

Cao cấp
Hello

5 bài học sâu sắc

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Mỗi sản phẩm đi kèm với những câu chuyện. Thành công của người khác là nguồn cảm hứng cho nhiều người theo sau. 5 bài học rút ra được đã thay đổi con người tôi mãi mãi. Còn bạn? Hãy bấm vào ngay!

Xem tất cả

Đăng ký nhận thông báo bài viết mới

hoặc
* Bản tin tổng hợp được gửi mỗi 1-2 tuần, huỷ bất cứ lúc nào.

Bình luận (1)

Nội dung bình luận...
Avatar
Tiennx Business1 năm trước

bài viết hay quá anh Hoài. Mà e nghĩ những từ cần chú ý "keyword" vd như: 401,400,500,... thì nên đổi màu cho nổi để dễ nhìn :D

Trả lời
Avatar
Xuân Hoài Tống1 năm trước

Ok luôn, a cũng thấy hơi lấn cấn 😅