← C4 Model: vẽ kiến trúc phần mềm

Bài 11 · Vận dụng · 22 phút

Tài liệu sống cùng repo

Biên soạn bởi Nguyễn Anh Tuấn

Mở rộng - docs-as-code: lưu tài liệu C4 + BA cạnh mã nguồn (docs/, Markdown + Mermaid, ADR), version & review qua Git/PR - một nguồn sự thật cho cả team.

Mèo con đã biết dựng và vẽ C4 đẹp. Nhưng trong công ty thật, một câu hỏi lớn còn đó: tài liệu sống ở đâu? Cảnh quen thuộc: sơ đồ nằm trong một slide cũ, tài liệu yêu cầu ở Confluence, code ở Git - và cả ba lệch nhau sau vài tháng.

  • Tài liệu tách rời code đổi chậm hơn code, nên mau lạc hậu.
  • Mỗi phòng ban giữ một bản "sự thật" riêng - CEO thấy một kiểu, dev thấy kiểu khác.
  • Khi tài liệu và code không khớp, người ta ngừng tin tài liệu - rồi ngừng đọc.

Bài Diagrams as code đã chữa được phần sơ đồ. Giờ ta mở rộng ý đó ra toàn bộ tài liệu.

Ý tưởng docs-as-code: đặt tài liệu ngay trong repo, viết bằng Markdown (và Mermaid cho sơ đồ), rồi để nó hưởng mọi thứ tốt của code.

  • Cùng repo với code: đổi code thì cập nhật tài liệu trong CÙNG một Pull Request.
  • Version theo Git: tài liệu có lịch sử, biết ai đổi gì, khi nào, vì sao.
  • Review qua PR: tài liệu được góp ý như code, không trôi nổi.
  • Một nguồn sự thật: mọi vai trò mở cùng một chỗ, không còn "bản nào mới nhất?".

Một cách tổ chức gọn gàng, đủ chỗ cho cả tài liệu kiến trúc lẫn nghiệp vụ:

cấu trúc thư mục repo (minh hoạ)

repo/
├── README.md            # diem vao: ai doc gi bat dau tu dau
├── src/                 # ma nguon
└── docs/
    ├── architecture/    # so do C4 (Mermaid/Structurizr)
    │   ├── context.md
    │   ├── container.md
    │   └── component-api.md
    ├── ba/              # tai lieu Business Analysis
    │   ├── user-stories.md
    │   ├── acceptance-criteria.md
    │   └── glossary.md   # tu dien thuat ngu chung
    └── adr/             # Architecture Decision Records
        ├── 0001-chon-postgresql.md
        └── 0002-tach-service-thanh-toan.md
  • architecture/: sơ đồ C4 các mức, viết bằng Mermaid để render thẳng trên GitHub.
  • ba/: tài liệu nghiệp vụ - user story, tiêu chí chấp nhận, và glossary (từ điển thuật ngữ chung).
  • adr/: nhật ký quyết định, đánh số tăng dần, không xoá quyết định cũ.

Tài liệu hay thiếu nhất là lý do. Sáu tháng sau, không ai nhớ vì sao chọn PostgreSQL thay vì MongoDB. ADR (Architecture Decision Record) giải quyết đúng chuyện đó - mỗi quyết định một file ngắn:

docs/adr/0001-chon-postgresql.md (mẫu ADR)

# 1. Chon PostgreSQL lam co so du lieu chinh

## Trang thai
Da chap nhan (2026-06-12)

## Boi canh
He thong vi dien tu can giao dich nhat quan (ACID) va bao cao quan he.
Doi da quen SQL.

## Quyet dinh
Dung PostgreSQL cho du lieu chinh.

## He qua
- Loi: giao dich ACID, kieu du lieu phong phu, cong dong lon.
- Danh doi: can ke hoach sharding neu sau nay tai rat lon.

Vì sao ADR đáng giá

ADR là append-only: quyết định cũ không xoá, chỉ đánh dấu "đã thay thế bởi ADR số X". Người mới vào đọc một lượt là hiểu hệ thống đã đi qua những ngã rẽ nào - thứ mà sơ đồ không kể được.

Đây là điều biến repo docs thành ngôn ngữ chung của cả công ty. Mỗi vai trò vào cùng một chỗ, đọc đúng tầng của mình:

CEO / Salesdocs/architecture/context.md + glossary - hiểu hệ thống làm gì, cho ai.
BAdocs/ba/* + cập nhật Context khi yêu cầu đổi.
PO / PMuser-stories + container.md - lên backlog, ước lượng.
DEVcontainer/component + ADR - biết viết code ở đâu, vì sao.

Và vì Mermaid render thẳng trên GitHub, ngay cả người không lập trình cũng thấy được sơ đồ như thế này:

System Context - Ngân Hàng Số

[Người dùng]

Khách hàng

Xem số dư, chuyển khoản, tra cứu giao dịch.

[Hệ thống phần mềm]

Ngân Hàng Số

Cho khách hàng giao dịch trực tuyến.

[Hệ thống ngoài]

Hệ thống lõi (Core Banking)

Nguồn sự thật về tài khoản & giao dịch.

[Hệ thống ngoài]

Dịch vụ Email

Gửi email thông báo giao dịch.

Quản lý tài khoản [HTTPS]Lấy số dư, ghi giao dịch [XML/HTTPS]Gửi email [SMTP]

Áp dụng dù công ty đã có gì

Chưa dùng docs-as-code? Bắt đầu nhỏ: thêm thư mục docs/ với một sơ đồ Context và một glossary. Đã có Confluence? Giữ nó cho tài liệu rộng, nhưng để tài liệu kiến trúc cạnh code và link qua lại - không cần đập đi làm lại.

Giờ tài liệu đã có nhà đúng chỗ - cạnh code, version được, ai cũng đọc. Nhưng viết hết chúng bằng tay thì tốn công. Đây là lúc một trợ thủ bước vào.

Bước tiếp theo

Bài tới: Dùng AI dựng tài liệu C4 & BA - để AI lo phần nháp, mèo con lo phần kiểm chứng và quyết định.

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

Không bắt buộc. Bạn có thể chạy song song: tài liệu kỹ thuật (C4, ADR) sống trong repo cạnh code, còn tài liệu rộng cho toàn công ty vẫn ở Confluence và LINK sang repo. Lợi ích chính của docs-as-code là tài liệu đổi cùng code trong cùng một Pull Request, nên ít lạc hậu.

Markdown rất dễ đọc, và GitHub/GitLab render đẹp cả Mermaid. Nếu cần thân thiện hơn, dùng MkDocs hay Docusaurus để xuất bản repo docs thành một trang web đọc như tài liệu thường - người không kỹ thuật vẫn xem thoải mái.

Repo có thể để private, hoặc tách tài liệu công khai/riêng. Quy tắc bất di bất dịch: KHÔNG để mật khẩu, khoá API, dữ liệu khách hàng trong tài liệu (hay bất cứ đâu trong repo) - tài liệu mô tả kiến trúc, không chứa bí mật.

ADR (Architecture Decision Record) ghi lại MỘT quyết định kiến trúc: bối cảnh, lựa chọn, và hệ quả. Nó append-only theo thời gian: quyết định cũ không xoá mà đánh dấu "đã thay thế". Nhờ vậy người mới hiểu được "vì sao hồi đó chọn thế này".

Vừa đủ để người mới hiểu hệ thống và để các quyết định quan trọng không bị quên. Tài liệu không ai đọc, không ai cập nhật là tài liệu chết - thà ít mà sống còn hơn nhiều mà lạc hậu.

Tick những điều em tự tin làm được. Càng lên cao, em càng hiểu sâu.

Tick những điều em tự tin làm được sau khi học bài này. 0/6

Trả lời vài câu để chắc rằng em đã nắm bài.

Câu 1/3 Điểm: 0

Lợi ích cốt lõi của docs-as-code (tài liệu cạnh code) là gì?

  1. 1

    Dựng cây docs/

    Phác cấu trúc thư mục docs/ cho một dự án mèo con biết: nơi để sơ đồ C4, tài liệu BA, và ADR.

    Hoàn thành khi: Cây thư mục có ít nhất ba nhánh (architecture, ba, adr) và một README dẫn đường.

  2. 2

    Viết một ADR

    Chọn một quyết định (vd "dùng PostgreSQL thay vì MongoDB"). Viết một ADR theo cấu trúc Bối cảnh - Quyết định - Hệ quả - Trạng thái.

    Hoàn thành khi: ADR đủ bốn phần; phần Hệ quả nêu cả mặt lợi và mặt phải đánh đổi.

  3. 3

    Đưa sơ đồ vào repo

    Viết một sơ đồ C4 bằng Mermaid, lưu thành file trong docs/architecture, và render thử trên GitHub (hoặc trình xem Mermaid).

    Hoàn thành khi: File .md chứa sơ đồ Mermaid render được; có tiêu đề và quan hệ có nhãn.

  4. 4

    README dẫn đường

    Viết mục lục cho README của repo: mỗi vai trò (CEO/Sales, BA, PM, DEV) nên bắt đầu đọc từ đâu trong docs/.

    Hoàn thành khi: README trỏ đường cho ít nhất ba vai trò tới đúng tài liệu phù hợp.

  5. 5

    Confluence hay repo?

    Lập luận: tài liệu nào nên ở repo, tài liệu nào nên ở Confluence/Notion, và chúng liên kết với nhau ra sao.

    Hoàn thành khi: Phân loại rõ ≥3 loại tài liệu; nêu cách hai nơi liên kết (link, mirror).

  6. 6

    Một nguồn sự thật

    Mô tả: khi đổi cơ sở dữ liệu, những tài liệu nào trong repo cần cập nhật, và vì sao gói chúng cùng một Pull Request là tốt.

    Hoàn thành khi: Liệt kê ≥2 tài liệu bị ảnh hưởng (vd sơ đồ Container, ADR); giải thích lợi ích của việc cập nhật cùng PR.