Thiết kế API dễ dùng để người khác không phải đoán

Một API tốt giống như một cánh cửa được thiết kế khéo: người dùng đẩy đúng chiều mà chẳng cần suy nghĩ, không cần bảng hướng dẫn dán bên cạnh. Ngược lại, một API tệ buộc người dùng phải đọc mã nguồn, thử sai liên tục và chửi thầm tác giả. Dù bạn đang xây một API web cho đối tác bên ngoài hay chỉ là một thư viện nội bộ cho đồng nghiệp, những nguyên tắc thiết kế cốt lõi vẫn giống nhau: làm cho việc dùng đúng trở nên dễ dàng và việc dùng sai trở nên khó khăn. Bài viết này bàn về những nguyên tắc đó dưới góc nhìn thực dụng.
API là một hợp đồng, không phải một chi tiết cài đặt
Khác biệt lớn nhất giữa code bên trong và API là mức độ ràng buộc. Code bên trong bạn có thể sửa tự do vì chỉ mình bạn dùng. Nhưng một khi API đã được công bố và có người phụ thuộc vào nó, mỗi thay đổi đều có thể làm hỏng ứng dụng của họ. Vì thế API cần được xem như một lời hứa dài hạn: bạn cam kết rằng khi người ta gọi hàm này với tham số kia, họ sẽ nhận lại kết quả có hình dạng đúng như đã thỏa thuận.
Hệ quả thực tế là bạn nên đầu tư suy nghĩ kỹ ngay từ đầu, vì sửa một API đã phát hành đắt hơn nhiều so với sửa code nội bộ. Đồng thời nên giấu đi càng nhiều chi tiết bên trong càng tốt. Mọi thứ bạn để lộ ra đều trở thành thứ người khác có thể dựa vào, và do đó trở thành thứ bạn buộc phải giữ nguyên về sau. Bề mặt càng nhỏ gọn, bạn càng có nhiều tự do thay đổi phần ruột mà không làm phiền ai.
Đặt tên và cấu trúc theo cách người dùng nghĩ
Người gọi API không quan tâm bên trong bạn tổ chức dữ liệu ra sao; họ quan tâm đến bài toán của họ. Một API tốt phản ánh mô hình tư duy của người dùng chứ không phải sơ đồ cơ sở dữ liệu của bạn. Nếu một người mới đọc tên hàm và tên tham số mà đoán được ngay chúng làm gì, bạn đã thắng một nửa. Sự nhất quán ở đây quan trọng đến mức gần như thiêng liêng: nếu một chỗ dùng từ “xóa” thì đừng chỗ khác lại dùng “gỡ bỏ” cho cùng một ý; nếu danh sách trả về theo một thứ tự nào đó, hãy giữ đúng quy ước ấy ở mọi nơi.
Vài điều đáng lưu tâm khi thiết kế bề mặt của API:
- Dùng từ ngữ nhất quán cho cùng một khái niệm trong toàn bộ API.
- Để những tham số bắt buộc lên trước, tham số tùy chọn ra sau, và tránh những danh sách tham số dài dằng dặc khó nhớ thứ tự.
- Chọn giá trị mặc định hợp lý để trường hợp phổ biến nhất dùng được ngay mà không phải cấu hình thêm gì.
- Trả về dữ liệu có cấu trúc ổn định, đừng lúc trả một kiểu lúc trả một kiểu khác tùy tình huống.
Xử lý lỗi rõ ràng và trung thực
Phần bị xem nhẹ nhất trong thiết kế API lại chính là cách nó báo lỗi. Khi mọi thứ suôn sẻ thì API nào cũng trông ổn; chất lượng thật sự lộ ra khi có chuyện không như ý. Một API tốt phân biệt rõ các loại tình huống: lỗi do người gọi truyền sai, lỗi do hệ thống bên trong trục trặc, và những trường hợp tuy bất thường nhưng vẫn hợp lệ. Người gọi cần đủ thông tin để biết chuyện gì đã xảy ra và nên làm gì tiếp theo.
Thông báo lỗi mơ hồ kiểu “đã có lỗi xảy ra” là một sự tra tấn với người tích hợp. Hãy nói rõ trường nào sai, vì sao sai, và nếu được thì gợi ý cách khắc phục. Đồng thời giữ cho cách báo lỗi nhất quán trên toàn API: nếu chỗ này ném ngoại lệ, chỗ kia lại trả về một giá trị đặc biệt, người dùng sẽ không bao giờ biết phải đề phòng kiểu nào. Sự nhất quán trong xử lý lỗi giúp người ta viết code phòng vệ một lần và yên tâm áp dụng ở khắp nơi.
Thiết kế cho sự thay đổi ngay từ đầu
Không API nào đứng yên mãi mãi. Nhu cầu thay đổi, và bạn sẽ cần bổ sung. Câu hỏi không phải là có thay đổi hay không, mà là thay đổi có làm hỏng những người đang dùng hay không. Một thiết kế khôn ngoan luôn để ngỏ đường mở rộng mà không phá vỡ cam kết cũ: thêm một hàm mới thì an toàn, nhưng đổi ý nghĩa của một hàm đang tồn tại thì rất nguy hiểm.
Một số cách giúp API tiến hóa êm ả:
- Ưu tiên thêm mới thay vì sửa đổi hoặc xóa bỏ những gì đã công bố.
- Nếu buộc phải thay đổi phá vỡ tương thích, hãy đánh phiên bản rõ ràng và cho người dùng đủ thời gian chuyển đổi.
- Đánh dấu những phần sắp bị loại bỏ từ sớm, kèm hướng dẫn thay thế, thay vì cắt bỏ một cách bất ngờ.
- Tránh để lộ ra những chi tiết bên trong mà bạn biết chắc là sẽ còn thay đổi.
Tài liệu và ví dụ là một phần của thiết kế
Một API chưa có tài liệu tốt thì coi như chưa hoàn thành, dù code có đẹp đến đâu. Nhưng tài liệu tốt không phải là liệt kê máy móc từng hàm; nó là kể cho người ta biết nên bắt đầu từ đâu và làm thế nào để giải quyết những bài toán thường gặp. Một ví dụ chạy được có giá trị hơn nhiều đoạn mô tả trừu tượng, vì người ta thường học bằng cách sao chép rồi chỉnh sửa cho hợp với hoàn cảnh của mình.
Có một bài kiểm tra đơn giản để đánh giá API của bạn: đưa nó cho một đồng nghiệp chưa từng thấy nó bao giờ và lặng lẽ quan sát họ cố dùng mà không hỏi bạn. Mỗi lần họ khựng lại, mỗi lần họ đoán sai, đều là một khiếm khuyết trong thiết kế đang chỉ thẳng vào bạn. Lắng nghe những khoảnh khắc bối rối đó và gọt giũa cho đến khi cánh cửa của bạn tự nói cho người ta biết phải đẩy chiều nào, đó chính là lúc bạn đã thiết kế được một API thật sự đáng dùng.