DEV Community

Cover image for Cách thiết kế và phát triển API chuẩn Git-native?
Sebastian Petrus
Sebastian Petrus

Posted on • Originally published at apidog.com

Cách thiết kế và phát triển API chuẩn Git-native?

Hầu hết các đội API vẫn viết mã trước, rồi tạo đặc tả sau. Kết quả thường là hợp đồng API và implementation lệch nhau theo thời gian. Thiết kế API gốc Git đảo ngược quy trình đó: coi hợp đồng API như mã nguồn, quản lý phiên bản trong Git, review thay đổi qua pull request, rồi dùng đặc tả đã commit để tạo mock, kiểm thử và tài liệu.

Dùng thử Apidog ngay hôm nay

Bài viết này tập trung vào cách triển khai quy trình đó trong thực tế: thiết kế hợp đồng trên branch, review trong PR, chạy lint trong CI, và biến OpenAPI spec thành mock, test, docs hoặc codegen. Mục tiêu là để lịch sử Git của bạn cũng chính là lịch sử API.

Nếu bạn đã quen với mô hình Spec-First và muốn xem hướng dẫn theo sản phẩm, hãy đọc thêm bài viết về quy trình làm việc API gốc Git. Bài viết này tập trung vào thực hành.

"Git-native" có nghĩa gì đối với công việc API

Git-native nghĩa là định nghĩa API của bạn nằm trong repository dưới dạng tệp văn bản thuần túy, ví dụ openapi.yaml hoặc openapi.json.

Không phải trong database riêng của một nền tảng cloud. Không phải chỉ chỉnh được qua UI của nhà cung cấp. Không phải một bản export lỗi thời được copy vào repo.

Trong mô hình gốc Git:

  • Tệp spec trong main là hợp đồng chính thức.
  • Mọi thay đổi đi qua branch, commit, pull request và merge.
  • Mock, docs, test, client hoặc server stub được tạo từ spec đã commit.

Git-native API workflow

Cách làm này giúp bạn có lịch sử thay đổi, trách nhiệm, rollback và review cho chính bề mặt API, giống như cách bạn đang làm với source code.

Một thiết lập Git-native tối thiểu cần có:

repo/
  api/
    openapi.yaml
  src/
  .github/
    workflows/
Enter fullscreen mode Exit fullscreen mode

Tệp api/openapi.yaml là nguồn sự thật duy nhất. GUI, mock server, documentation site hoặc codegen chỉ là các lớp đọc từ tệp đó.

Tại sao nên thiết kế và phát triển API trong Git

Bạn đã dùng Git để bảo vệ mã nguồn. Hợp đồng API cũng nên được quản lý tương tự.

1. Có lịch sử rõ ràng

Khi ai đó hỏi:

Chúng ta thêm tham số cursor từ khi nào?

Bạn có thể kiểm tra ngay:

git log -p -- api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

Commit liên quan sẽ có tác giả, thời gian, diff và lý do thay đổi.

2. Truy vết được trách nhiệm

Nếu một field gây nhầm lẫn, chạy:

git blame api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

Bạn sẽ biết dòng đó được thêm bởi ai, trong commit nào, và thường có thể truy ngược về PR thảo luận thiết kế.

3. Rollback đơn giản

Nếu một thiết kế sai đã được merge, bạn có thể revert:

git revert <merge_commit_sha>
Enter fullscreen mode Exit fullscreen mode

Sau đó, mock, docs, test và codegen được tạo lại từ spec đã revert. Không cần sửa thủ công trong một hệ thống khác.

4. Review thiết kế trước khi viết code

Pull request là nơi phù hợp để tranh luận về:

  • Endpoint path
  • Naming convention
  • Request/response schema
  • HTTP status code
  • Pagination
  • Breaking changes

Ví dụ: reviewer có thể bình luận trực tiếp trên dòng YAML thêm một field bắt buộc, trước khi backend hoặc frontend phụ thuộc vào nó.

5. Một nguồn sự thật duy nhất

Khi contract nằm trong main, frontend, backend, QA và documentation đều đọc cùng một file. Đây là nền tảng của một quy trình làm việc đặc tả API dựa trên Git.

Vòng lặp thiết kế API gốc Git

Một workflow đơn giản gồm 5 bước:

Thiết kế contract → Commit → Mở PR → Review → Merge
Enter fullscreen mode Exit fullscreen mode

Implementation nên đi sau bước merge, không phải ngược lại.

Giả sử bạn muốn thêm endpoint lấy danh sách hóa đơn của người dùng.

Bước 1: Tạo branch

git checkout -b feat/api-invoices-list
Enter fullscreen mode Exit fullscreen mode

Bước 2: Chỉnh sửa OpenAPI spec

# api/openapi.yaml
paths:
  /users/{userId}/invoices:
    get:
      operationId: listUserInvoices
      summary: List invoices for a user
      parameters:
        - name: userId
          in: path
          required: true
          schema:
            type: string
            format: uuid
        - name: status
          in: query
          required: false
          schema:
            type: string
            enum: [draft, open, paid, void]
      responses:
        "200":
          description: A page of invoices
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/InvoiceList"
        "404":
          description: User not found
Enter fullscreen mode Exit fullscreen mode

Bước 3: Commit thay đổi nhỏ và rõ ràng

git add api/openapi.yaml
git commit -m "Add GET /users/{userId}/invoices contract"
Enter fullscreen mode Exit fullscreen mode

Commit nên mô tả một quyết định thiết kế cụ thể, không gom quá nhiều endpoint trong cùng một lần.

Bước 4: Mở pull request

Trong PR, reviewer sẽ thấy diff cụ thể:

  • Một path mới
  • Một operation mới
  • Hai parameters
  • Hai response cases

Đây là thời điểm tốt để thảo luận:

  • Có cần pagination không?
  • status enum đã đủ chưa?
  • 404 có đúng khi user không tồn tại không?
  • Response schema có nhất quán với các endpoint khác không?

Bước 5: Merge và triển khai

Sau khi PR được duyệt, merge vào main.

git checkout main
git pull
Enter fullscreen mode Exit fullscreen mode

Từ thời điểm này, contract đã được thống nhất. Backend implementation, frontend integration, mock và test có thể bám vào spec đó. Đây là ý nghĩa thực tế của phát triển API spec-first: thỏa thuận đi trước mã.

Chiến lược phân nhánh cho hợp đồng API

Hãy xử lý API contract như source code: một branch cho mỗi đơn vị thay đổi logic.

Loại thay đổi Tiền tố branch Ví dụ Mức độ review
Endpoint mới feat/api- feat/api-invoices-list Tiêu chuẩn
Thêm field feat/api- feat/api-invoice-currency Nhẹ
Breaking change break/api- break/api-remove-legacy-id Nặng, cần xác nhận
Sửa lỗi spec fix/api- fix/api-status-enum-typo Nhẹ
Refactor spec chore/api- chore/api-reorder-schemas Nhẹ

Tiền tố branch giúp reviewer hiểu mức độ rủi ro ngay từ tên branch.

Ví dụ:

git checkout -b break/api-remove-legacy-id
Enter fullscreen mode Exit fullscreen mode

Branch này nên kích hoạt review kỹ hơn, vì có khả năng ảnh hưởng client hiện tại.

Trunk-based hay Gitflow?

Mô hình Phù hợp với Đánh đổi với API
Trunk-based Continuous delivery, đội nhỏ đến vừa Contract tiến hóa theo thay đổi nhỏ, ít merge conflict
Gitflow Release theo lịch, môi trường có quy định chặt Spec có thể phân kỳ trên develop, merge lớn hơn

Với đa số đội API, trunk-based phù hợp hơn:

  • Branch ngắn hạn
  • PR nhỏ
  • Merge thường xuyên
  • Ít xung đột YAML

Các branch tồn tại lâu dễ làm spec lệch nhau, đặc biệt khi nhiều người cùng sửa một file lớn.

Review thiết kế API trong pull request

Một PR spec không chỉ là kiểm tra cú pháp YAML. Nó là review thiết kế API.

Reviewer nên kiểm tra ít nhất 4 nhóm câu hỏi.

1. Thay đổi này có gây hỏng client hiện tại không?

Các thay đổi có thể gây hỏng gồm:

  • Xóa field
  • Đổi tên field
  • Đổi kiểu dữ liệu
  • Xóa enum value
  • Biến optional field thành required
  • Đổi path hoặc method
  • Thắt chặt validation

Ví dụ diff an toàn hơn:

 parameters:
   - name: status
     in: query
     schema:
       type: string
-      enum: [draft, open, paid, void]
+      enum: [draft, open, paid, void, uncollectible]
Enter fullscreen mode Exit fullscreen mode

Thêm enum value thường là thay đổi bổ sung. Nhưng nếu xóa void, client đang gửi giá trị đó có thể bị hỏng.

2. Naming có nhất quán không?

Kiểm tra các mẫu đã có:

  • API dùng plural noun hay singular noun?
  • Error response có field code, message hay cấu trúc khác?
  • Timestamp dùng createdAt hay created_at?
  • ID dùng id, userId hay user_id?

Ví dụ nếu API hiện tại dùng camelCase:

{
  "createdAt": "2026-06-01T10:00:00Z"
}
Enter fullscreen mode Exit fullscreen mode

Không nên thêm field mới kiểu snake_case:

{
  "created_at": "2026-06-01T10:00:00Z"
}
Enter fullscreen mode Exit fullscreen mode

3. Diff có dễ review không?

Giữ YAML ổn định:

  • Không format lại toàn bộ file trong cùng PR thêm endpoint.
  • Sắp xếp key theo convention.
  • Thêm path vào vị trí dễ đoán.
  • Chia file lớn nếu cần.

Một diff 20 dòng dễ review hơn một diff 500 dòng chứa cả thay đổi thật lẫn reformat.

4. Có đủ response case không?

Đừng chỉ định nghĩa 200.

Ví dụ với endpoint tạo invoice, nên cân nhắc:

responses:
  "201":
    description: Invoice created
  "400":
    description: Invalid request
  "401":
    description: Unauthorized
  "409":
    description: Duplicate invoice
Enter fullscreen mode Exit fullscreen mode

Review tốt giúp tránh sửa thiết kế sau khi implementation đã hoàn tất.

Từ thiết kế đến phát triển

Sau khi contract đã nằm trong main, hãy tạo artifact từ spec thay vì viết thủ công.

From API design to development

1. Tạo code từ OpenAPI

Ví dụ dùng openapi-generator:

npx @openapitools/openapi-generator-cli generate \
  -i api/openapi.yaml \
  -g typescript-fetch \
  -o generated/client
Enter fullscreen mode Exit fullscreen mode

Hoặc tạo server stub:

npx @openapitools/openapi-generator-cli generate \
  -i api/openapi.yaml \
  -g nodejs-express-server \
  -o generated/server
Enter fullscreen mode Exit fullscreen mode

Handler của bạn vẫn chứa business logic, nhưng request/response shape được ràng buộc bởi contract.

2. Tạo mock server

Mock server đọc spec và trả response mẫu. Frontend có thể bắt đầu trước khi backend hoàn tất.

Ví dụ với Prism:

npx @stoplight/prism-cli mock api/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

Frontend gọi mock endpoint thay vì chờ backend production-ready.

3. Chạy contract test

Contract test xác thực server đang chạy có khớp với OpenAPI spec không.

Ý tưởng cơ bản:

Gửi request thực tế → Nhận response → Validate response theo schema → Fail CI nếu lệch
Enter fullscreen mode Exit fullscreen mode

Điều này biến drift giữa spec và code thành lỗi pipeline, không phải lỗi production.

4. Tạo tài liệu API

Reference docs nên được tạo từ openapi.yaml.

Khi spec thay đổi, docs thay đổi cùng commit. Không có bước cập nhật tài liệu thủ công để bị quên.

Nguyên tắc chung:

Một spec đã commit → nhiều artifact được generate
Enter fullscreen mode Exit fullscreen mode

Các quy ước nhóm có thể mở rộng

Để workflow Git-native không rối khi nhóm lớn hơn, hãy thống nhất convention sớm.

1. Chọn cấu trúc spec

Với API nhỏ, một file là đủ:

api/
  openapi.yaml
Enter fullscreen mode Exit fullscreen mode

Với API lớn, nên tách file:

api/
  openapi.yaml
  paths/
    users.yaml
    invoices.yaml
  schemas/
    user.yaml
    invoice.yaml
Enter fullscreen mode Exit fullscreen mode

Sau đó bundle lại trong CI hoặc build step.

Ví dụ dùng Redocly CLI:

npx @redocly/cli bundle api/openapi.yaml -o dist/openapi.yaml
Enter fullscreen mode Exit fullscreen mode

2. Quản lý version có chủ đích

Cập nhật info.version khi có thay đổi có ý nghĩa:

openapi: 3.1.0
info:
  title: Billing API
  version: 1.4.0
Enter fullscreen mode Exit fullscreen mode

Gợi ý:

  • Patch: sửa lỗi mô tả hoặc schema không gây ảnh hưởng
  • Minor: thêm endpoint, thêm optional field
  • Major: breaking change

Breaking change thường cần version mới rõ ràng, ví dụ /v2.

3. Duy trì changelog

Đặt CHANGELOG.md cạnh spec:

# Changelog

## 1.4.0

- Add `GET /users/{userId}/invoices`
- Add `status` query parameter for invoice filtering
Enter fullscreen mode Exit fullscreen mode

Git log chính xác nhưng dài. Changelog giúp consumer đọc nhanh những gì thay đổi.

4. Bảo vệ spec bằng CODEOWNERS

Ví dụ với GitHub:

# .github/CODEOWNERS
/api/openapi.yaml @api-stewards
/api/paths/ @api-stewards
/api/schemas/ @api-stewards
Enter fullscreen mode Exit fullscreen mode

Mọi PR sửa contract sẽ cần API steward review.

5. Chạy lint trong CI

Ví dụ workflow dùng Spectral:

# .github/workflows/api-lint.yml
name: API Lint

on:
  pull_request:
    paths:
      - "api/**"

jobs:
  spectral:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run Spectral
        run: npx @stoplight/spectral-cli lint api/openapi.yaml --fail-severity warn
Enter fullscreen mode Exit fullscreen mode

Lint giúp bắt lỗi style, naming hoặc thiếu field trước khi con người review thiết kế.

Kết hợp tối thiểu nên có:

CODEOWNERS + API lint + PR review
Enter fullscreen mode Exit fullscreen mode

Bộ ba này đủ để mở rộng từ vài kỹ sư lên nhiều team.

Các cạm bẫy phổ biến và cách tránh

1. Spec và code lệch nhau

Vấn đề:

Spec nói response có field `currency`
Server thực tế không trả `currency`
Enter fullscreen mode Exit fullscreen mode

Cách tránh:

  • Generate stub/client từ spec
  • Chạy contract test trong CI
  • Fail build nếu response không khớp schema

2. PR quá lớn

Một PR thêm 20 endpoint rất khó review. Reviewer dễ đọc lướt và bỏ sót lỗi thiết kế.

Cách tránh:

  • Một endpoint hoặc một nhóm thay đổi nhỏ cho mỗi PR
  • Tách refactor spec khỏi thay đổi semantic
  • Không reformat toàn bộ file trong PR tính năng

3. Artifact viết tay

Nếu client, docs hoặc mock được viết tay, chúng sẽ lệch khỏi spec.

Cách tránh:

  • Generate client
  • Generate docs
  • Generate mock
  • Xem artifact viết tay như dấu hiệu cần kiểm tra lại workflow

4. Merge conflict YAML

Hai branch cùng sửa một file OpenAPI lớn có thể tạo conflict khó xử lý.

Cách tránh:

  • Branch ngắn hạn
  • PR nhỏ
  • Thứ tự key ổn định
  • Tách spec thành nhiều file theo resource
  • Bundle ở build step

Mẫu chung cho cả bốn vấn đề:

Giữ thay đổi nhỏ → Generate từ spec → Dùng CI để thực thi contract
Enter fullscreen mode Exit fullscreen mode

Vị trí của Apidog

Bạn có thể triển khai workflow Git-native chỉ với editor, Git và CLI. Tuy nhiên, nhiều đội vẫn muốn có giao diện trực quan để thiết kế API mà không từ bỏ Git làm nguồn sự thật.

Đó là vai trò của Chế độ Spec-First trong Apidog.

Chế độ Spec-First giữ tệp OpenAPI trong Git repository của bạn và hỗ trợ đồng bộ hai chiều. Bạn có thể chỉnh contract trong trình thiết kế trực quan của Apidog hoặc chỉnh trực tiếp trong editor. Cả hai đều nhất quán với file trong repo.

Tệp trong Git vẫn là bản chính thức, nên branch, PR, review, history và rollback vẫn hoạt động như mô tả ở trên. Apidog trở thành một giao diện thiết kế đọc và ghi vào workflow Git-native, không thay thế Git.

Xem thêm tài liệu Chế độ Spec-First để biết chi tiết cài đặt.

Câu hỏi thường gặp

Thiết kế API gốc Git chỉ dành cho OpenAPI?

Không. Nguyên tắc này áp dụng cho mọi định dạng contract dạng text có thể diff, branch và review.

Ví dụ:

  • OpenAPI
  • AsyncAPI
  • gRPC .proto
  • GraphQL SDL

OpenAPI phổ biến nhất cho REST API, nhưng Git-native là quy trình, không phải định dạng duy nhất.

Làm thế nào để xử lý breaking change?

Hãy làm breaking change thật rõ ràng:

  • Dùng branch prefix break/api-
  • Tăng major version
  • Yêu cầu API steward phê duyệt qua CODEOWNERS
  • Ghi vào CHANGELOG.md
  • Nếu có thể, thêm format mới trước và deprecate format cũ sau

Ví dụ:

git checkout -b break/api-remove-legacy-id
Enter fullscreen mode Exit fullscreen mode

Breaking change không nên xuất hiện như một dòng sửa nhỏ bị giấu trong PR lớn.

Spec API có nên nằm cùng repository với mã nguồn không?

Thường là có, nếu cùng một team sở hữu cả contract và implementation.

Lợi ích:

  • Một PR có thể thay đổi contract và handler liên quan
  • CI chạy lint và contract test trong cùng pipeline
  • Dễ truy vết từ spec sang implementation

Chỉ nên tách spec sang repo riêng khi nhiều team cùng tiêu thụ một API chia sẻ và cần quản lý version độc lập.

Làm thế nào để ngăn spec và code bị lệch?

Thêm contract test vào CI.

Quy trình:

Start server → Send request → Validate response against committed spec → Fail if mismatch
Enter fullscreen mode Exit fullscreen mode

Kết hợp thêm:

  • Generate client từ spec
  • Generate server stub từ spec
  • Generate docs từ spec
  • Không sửa artifact generate bằng tay

Kết luận

Thiết kế API gốc Git là một nguyên tắc triển khai: coi hợp đồng API như mã nguồn. Đặt spec trong repository, phát triển trên branch, review qua pull request, merge vào main, rồi generate artifact từ file đã commit.

Bắt đầu nhỏ:

  1. Di chuyển OpenAPI spec vào repo.
  2. Thêm API lint trong CI.
  3. Dùng CODEOWNERS để yêu cầu review.
  4. Chia PR theo từng thay đổi nhỏ.
  5. Generate mock, docs, client hoặc server stub từ spec.
  6. Thêm contract test để chống drift.

Khi workflow này ổn định, Git history của bạn sẽ trở thành bản ghi đầy đủ về cách API tiến hóa: ai thay đổi, thay đổi gì, khi nào, vì sao, và được review như thế nào.

Top comments (0)