OpenAPI Generator: Giải pháp ‘cứu rỗi’ Developer khỏi việc viết Client SDK bằng tay

Development tutorial - IT technology blog
Development tutorial - IT technology blog

Cơn ác mộng lúc 2 giờ sáng và cái giá của việc code tay

Điện thoại rung liên hồi. Sentry báo lỗi đỏ rực: TypeError: Cannot read property 'data' of undefined. Hệ thống production sập chỉ vì Backend đổi một field từ user_id thành userId. Phía Frontend vẫn gọi theo tên cũ do tài liệu API chưa cập nhật kịp, và tệ hơn là toàn bộ API Client đều được viết tay.

Tôi từng tham gia refactor dự án Fintech với hơn 50.000 dòng code. Bài học xương máu là: nếu Backend và Client không đồng nhất tuyệt đối, mọi nỗ lực viết test đều vô nghĩa khi schema thay đổi. Việc ngồi gõ từng dòng axios.get hay định nghĩa thủ công hàng trăm interface TypeScript không chỉ gây nhàm chán. Đó còn là cái bẫy dẫn đến những lỗi typo ngớ ngẩn nhưng để lại hậu quả nghiêm trọng.

Ba kịch bản thường gặp khi kết nối API

Đa số các đội ngũ phát triển hiện nay thường xử lý việc giao tiếp giữa các dịch vụ theo một trong ba cách sau:

1. Thủ công mỹ nghệ (Manual Implementation)

Bạn mở Swagger, nhìn endpoint rồi copy-paste vào code. Cách này giúp bạn kiểm soát từng dòng code nhưng cực kỳ kém hiệu quả khi dự án phình to. Thử tưởng tượng dự án có 100 endpoints, chỉ cần Backend đổi kiểu dữ liệu từ int sang string, bạn sẽ phải lùng sục hàng chục file để sửa lại bằng tay.

2. Dùng thư viện Generic (Shared Libraries)

Nhiều team chọn viết các wrapper dùng chung. Tuy nhiên, rào cản lớn nhất vẫn là “Type-safety”. Bạn vẫn phải tự định nghĩa lại Model cho từng ngôn ngữ, dẫn đến tình trạng “râu ông nọ chắp cằm bà kia”.

3. Tự động hóa với OpenAPI Generator

Đây là lựa chọn của các hệ thống Microservices hiện đại. Chỉ với một file openapi.yaml, công cụ này sẽ tự động sinh ra toàn bộ mã nguồn Client SDK cho TypeScript, Python, Go hay Java trong vài giây.

Ưu và nhược điểm: Có thần thánh như lời đồn?

Ưu điểm:

  • Chính xác 100%: SDK sinh ra luôn khớp hoàn toàn với API Spec.
  • Đa ngôn ngữ: Một file spec duy nhất dùng được cho cả Mobile (Dart/Swift), Web (TypeScript) và Backend-to-Backend (Go/Python).
  • Tăng tốc độ bàn thờ: Thay vì mất 2 ngày viết boilerplate, bạn chỉ cần 2 giây chạy lệnh.

Nhược điểm:

  • Code hơi rườm rà: File sinh ra thường chứa nhiều comment dài dòng và boilerplate dư thừa.
  • Cấu hình phức tạp: Bạn cần thời gian làm quen với template Mustache nếu muốn tùy chỉnh code theo style riêng của team.

Triển khai thực tế: Từ Spec sang Code trong tích tắc

Hãy đảm bảo Backend của bạn đã xuất ra file api-spec.yaml chuẩn. Nếu chưa, hãy yêu cầu họ cung cấp trước khi bắt đầu.

Bước 1: Cài đặt qua Docker

Thay vì cài đặt Java hay Node.js rườm rà, tôi luôn ưu tiên dùng Docker. Cách này đảm bảo mọi thành viên trong team, từ máy Windows đến Mac, đều dùng chung một phiên bản generator.

docker pull openapitools/openapi-generator-cli

Bước 2: Sinh SDK cho TypeScript (Axios)

Frontend cần sự chặt chẽ về Type để tránh lỗi runtime. Để tạo SDK sử dụng Axios, hãy thực thi lệnh:

docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
    -i /local/api-spec.yaml \
    -g typescript-axios \
    -o /local/sdk/typescript

Trong thư mục sdk/typescript, bạn sẽ thấy file api.ts chứa đầy đủ các interface. Việc sử dụng giờ đây rất nhàn:

import { UserApi } from './sdk/typescript';

const userApi = new UserApi();
// Intellisense sẽ gợi ý chính xác tham số và kiểu dữ liệu trả về
const userInfo = await userApi.getUserById(123);

Bước 3: Sinh SDK cho Python và Go

Với Python, generator sẽ tạo luôn file setup.py để bạn đóng gói thành package nội bộ. Với Go, các struct sẽ được định nghĩa chặt chẽ, giúp tận dụng tối đa sức mạnh của static typing.

# Cho Python
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
    -i /local/api-spec.yaml -g python -o /local/sdk/python

# Cho Go
docker run --rm -v "${PWD}:/local" openapitools/openapi-generator-cli generate \
    -i /local/api-spec.yaml -g go -o /local/sdk/go

Kinh nghiệm thực chiến: Đừng dùng cấu hình mặc định

Sai lầm lớn nhất của tôi khi mới bắt đầu là bê nguyên xi code được sinh ra vào source code chính. Mỗi lần cập nhật API, toàn bộ các tùy chỉnh thủ công trong SDK đều bị ghi đè sạch bách.

Hãy lưu ý 3 quy tắc sau:

  1. Luôn dùng .openapi-generator-ignore: File này hoạt động giống .gitignore. Nó bảo vệ các file cấu hình custom của bạn không bị generator ghi đè.
  2. Tích hợp CI/CD: Đừng bao giờ chạy lệnh generator bằng tay rồi commit. Hãy thiết lập GitHub Action để tự động tạo Pull Request cập nhật SDK mỗi khi file spec thay đổi.
  3. Chăm chút cho API Spec: Code sinh ra chỉ tốt khi Spec chất lượng. Nếu Spec thiếu description hoặc định nghĩa kiểu dữ liệu mập mờ, SDK của bạn sẽ tràn ngập kiểu any vô dụng.

Đầu tư một buổi chiều để setup OpenAPI Generator sẽ cứu bạn khỏi hàng chục đêm thức trắng debug. Nếu hệ thống của bạn có từ 3 service trở lên, đây không còn là lựa chọn “thêm thắt”, mà là yêu cầu bắt buộc để duy trì sự ổn định.

Share: