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
Cần đọc trước
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ì.
Giữ tài liệu sống
Phần tiêu đề “Giữ tài liệu sống”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.
Khi nào áp dụng / ngoại lệ
Phần tiêu đề “Khi nào áp dụng / ngoại lệ”| 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 |
Checklist ADR (khi review PR thêm ADR)
Phần tiêu đề “Checklist ADR (khi review PR thêm ADR)”- 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”)?
- Context nêu vấn đề cụ thể, ràng buộc, viết trung tính, không bán giải pháp?
- Có ít nhất hai phương án đã cân nhắc, mỗi cái có lý do bị loại?
- Decision viết chủ động, đủ cụ thể để kiểm tra code có tuân theo không?
- 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)?
- Có điều kiện để xem lại (“khi throughput vượt…, khi có Kafka Connect”)?
- Status, ngày, người quyết định, link supersede/liên quan đầy đủ? Số không trùng?
- Dài 1–2 trang? Dài hơn thì phần khám phá thuộc về design doc.
Checklist README cho một backend service
Phần tiêu đề “Checklist README cho một backend service”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:
- Một đoạn: service làm gì, không làm gì, thuộc bounded context nào.
- 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).
- Lệnh test, lint, migrate.
- Bảng config/env var hoặc link tới reference sinh tự động.
- Link:
docs/architecture.md(C4),docs/adr/,docs/runbooks/, OpenAPI, dashboard. - Owner (team, kênh chat), on-call rotation.
- Event publish/consume và API phụ thuộc, kèm link schema.
Tự kiểm tra
Phần tiêu đề “Tự kiểm tra”- 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ì?
- 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?
- Vì sao Consequences của ADR outbox phải nhắc tới idempotent consumer?
- 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?
- 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.