Bỏ qua để đến nội dung
Knowledge Hub

Giữ tài liệu sống: docs-as-code, owner và checklist review Trung cấp

Thời gian đọc ước tính: 5 phút

Trang này trả lời: vì sao docs chết, cơ chế nào giữ chúng sống, và review một PR có ADR hay README thì soát gì.

Nygard: “Large documents are never kept up to date.” Docs chết vì nằm xa code và không ai chịu trách nhiệm. Chữa bằng quy trình, không bằng ý chí.

Đang tải diagram…

Cơ chế Cách làm Vì sao hiệu quả
Docs-as-code Markdown trong repo, lint link trong CI Cùng version với code; diff và review được
Review cùng PR PR template có mục “Docs/ADR/runbook cần cập nhật?” Người hiểu thay đổi nhất viết docs lúc còn nhớ
Owner CODEOWNERS cho docs/adr/ và docs/runbooks/ GitHub tự request review owner khi PR chạm file của họ (trừ draft PR)
Hạn dùng Runbook có “cập nhật lần cuối”; rà runbook sau mỗi incident Runbook sai lúc incident tệ hơn không có runbook
Xoá mạnh tay Xoá doc mô tả thứ không còn tồn tại (git vẫn giữ lịch sử) Doc sai làm mất lòng tin vào mọi doc khác
Ngoại lệ: ADR ADR không xoá, chỉ supersede/deprecate Giá trị nằm ở lịch sử quyết định

Ví dụ CODEOWNERS (GitHub: pattern khớp sau cùng được ưu tiên):

# .github/CODEOWNERS
* @acme/checkout
/docs/adr/ @acme/checkout-leads
/docs/runbooks/ @acme/checkout @acme/sre

Ưu điểm

  • Docs trong repo: review được, version theo code, offline, grep được.
  • ADR nhỏ, bất biến: rẻ để viết, không bao giờ “lỗi thời” theo nghĩa sai sự thật.
  • Runbook link từ alert: giảm thời gian chẩn đoán cho người không viết code.

Nhược điểm

  • Người ngoài engineering (PM, CS) khó đọc/comment trong repo; design doc cần thảo luận rộng có thể phải ở công cụ khác.
  • Đòi hỏi kỷ luật review: PR template và CODEOWNERS chỉ nhắc, không ép được chất lượng.
  • Decision log dài thì khó tìm: cần index và tiêu đề là câu quyết định.
Tình huống Làm gì
Quyết định khó đảo ngược hoặc lệch convention, team bất kỳ quy mô Áp dụng ADR. Bắt đầu bằng ADR-0001 và quyết định tiếp theo; không cần viết bù toàn bộ lịch sử
Quyết định cũ đang bị hỏi lại nhiều Viết bù có chọn lọc. Ghi rõ “viết hồi tố ngày X, bối cảnh dựa trên trí nhớ của Y”
Prototype/spike sẽ vứt; quyết định trong một module, đảo ngược được trong một PR Ngoại lệ: commit message tốt là đủ
Quyết định cấp công ty (chọn cloud, ngôn ngữ chính) Ngoại lệ: nằm ở repo/không gian chung, ADR của service chỉ link tới
  1. Tiêu đề là câu quyết định (“Phát event qua outbox thay vì publish trực tiếp”), không phải danh từ (“Outbox”)?
  2. Context nêu vấn đề cụ thể, ràng buộc, viết trung tính, không bán giải pháp?
  3. Có ít nhất hai phương án đã cân nhắc, mỗi cái có lý do bị loại?
  4. Decision viết chủ động, đủ cụ thể để kiểm tra code có tuân theo không?
  5. Consequences có ít nhất một hệ quả xấu và việc phải làm kèm theo (runbook, alert, yêu cầu idempotent)?
  6. Có điều kiện để xem lại (“khi throughput vượt…, khi có Kafka Connect”)?
  7. Status, ngày, người quyết định, link supersede/liên quan đầy đủ? Số không trùng?
  8. Dài 1–2 trang? Dài hơn thì phần khám phá thuộc về design doc.

GitHub gợi ý README trả lời: project làm gì, vì sao hữu ích, bắt đầu thế nào, hỏi ai, ai bảo trì. Cho service nội bộ, cụ thể hoá thành:

  1. Một đoạn: service làm gì, không làm gì, thuộc bounded context nào.
  2. Quickstart chạy được từ máy trắng trong vài lệnh (chạy thử trong CI hoặc định kỳ để nó không mục).
  3. Lệnh test, lint, migrate.
  4. Bảng config/env var hoặc link tới reference sinh tự động.
  5. Link: docs/architecture.md (C4), docs/adr/, docs/runbooks/, OpenAPI, dashboard.
  6. Owner (team, kênh chat), on-call rotation.
  7. Event publish/consume và API phụ thuộc, kèm link schema.
  1. Team quyết định không cache số dư tài khoản. Có nên viết ADR không, và Context cần nêu gì?
  2. ADR-0012 chọn outbox polling. Một năm sau chuyển sang CDC. Những file nào thay đổi, và thay đổi thế nào?
  3. Vì sao Consequences của ADR outbox phải nhắc tới idempotent consumer?
  4. README đang giải thích vì sao dùng Kafka thay vì RabbitMQ. Theo Diátaxis, phần đó nên chuyển đi đâu?
  5. Design doc và ADR khác nhau ở điểm nào về thời điểm viết và việc cập nhật sau đó?

Tiếp theo: Lỗi hay gặp khi viết ADR, runbook, README.