← Về danh sách
Kỹ nghệ & Quản lý phần mềm
#C4모델#ADR#아키텍처문서화#품질속성#Docs-as-Code#Architecture Decision Records
Cập nhật lần cuối · 2026-09-18

Tài liệu hóa kiến trúc phần mềm dựa trên mô hình C4 và ADR

1. Tổng quan

Tài liệu hóa kiến trúc dựa trên mô hình C4 và ADR là phương pháp trực quan hóa cấu trúc phần mềm theo mức trừu tượng phù hợp với từng bên liên quan (C4), đồng thời lưu lại các lựa chọn thiết kế quan trọng cùng căn cứ·đánh đổi của chúng dưới dạng bản ghi quyết định (ADR) nhằm bảo đảm tính bền vững của tri thức kiến trúc.

Kiến trúc phần mềm không thể được truyền đạt chỉ bằng danh sách chức năng của hệ thống. Ranh giới giữa người dùng và hệ thống bên ngoài, đơn vị triển khai, kho dữ liệu, luồng gọi lúc chạy (runtime) và ranh giới bảo mật phải được giải thích cùng nhau thì người phụ trách phát triển·vận hành·bảo mật·kinh doanh mới cùng nhìn về một hệ thống. Tuy nhiên, nếu đưa mọi thứ vào một sơ đồ cấu trúc khổng lồ, số đường nối và hộp sẽ quá nhiều, khiến chính những ranh giới và phụ thuộc quan trọng lại không còn nhìn thấy được.

Mô hình C4 chia hệ thống thành các tầng Context, Container, Component, Code giống như phóng to bản đồ, và biểu diễn cấu trúc ở mức cần thiết. Ở mức cao, ngay cả bên liên quan không chuyên kỹ thuật cũng hiểu được trách nhiệm và phụ thuộc bên ngoài của hệ thống; ở mức thấp, nhà phát triển có thể lần theo sự phân rã nội bộ của một container cụ thể. Mục đích không phải là vẽ vô điều kiện sơ đồ ở mọi mức, mà là chọn góc nhìn (view) phù hợp với câu hỏi và người đọc.

Chỉ bằng hình vẽ thì khó giải thích “vì sao chọn cơ sở dữ liệu này” hay “vì sao dùng sự kiện thay vì gọi đồng bộ”. Theo thời gian, khi người phụ trách thay đổi, cấu trúc hiện tại vẫn còn nhưng các ràng buộc về quy định·hiệu năng·chi phí·tổ chức ở thời điểm đó thì biến mất. ADR ghi ngắn gọn một quyết định có ý nghĩa kiến trúc cùng với bối cảnh, lựa chọn, phương án thay thế và kết quả tại thời điểm đó, qua đó giảm sự mất mát ký ức này.

C4 và ADR không thay thế cho nhau. Nếu C4 cho thấy diện mạo hiện tại của hệ thống theo kiểu “cái gì ở đâu và được kết nối thế nào”, thì ADR bổ sung “vì sao chọn cấu trúc đó và đã chấp nhận cái giá nào”. Khi quản lý phiên bản hai sản phẩm này cùng kho mã nguồn và liên kết chúng với nhau, việc phát hiện sự không nhất quán giữa cấu trúc và quyết định khi thay đổi thiết kế trở nên dễ dàng hơn.

Trong bài làm của Kỹ sư chuyên nghiệp (Professional Engineer), không được thu nhỏ C4 thành một ký pháp sơ đồ đơn thuần hay ADR thành biên bản họp. Thứ nhất, phải rút ra các view cần thiết từ mối quan tâm của các bên liên quan và các thuộc tính chất lượng. Thứ hai, phải mô tả bằng câu văn ranh giới và trách nhiệm của các phần tử C4, và nêu rõ hướng·giao thức·ý nghĩa dữ liệu của các quan hệ. Thứ ba, ADR phải ghi không chỉ tác động tích cực mà cả hệ quả tiêu cực như chi phí hiệu năng·bảo mật·vận hành·chuyển đổi.

A. Bối cảnh ra đời và sự cần thiết

Bối cảnh thứ nhất là độ phức tạp ngày càng tăng của hệ thống phân tán. Thời kỳ ứng dụng đơn khối, chỉ cần đọc mã nguồn và tệp thực thi là có thể nắm đại khái cấu trúc, nhưng dịch vụ ngày nay gồm client web·di động, API, message broker, cache, nhiều kho dữ liệu và SaaS bên ngoài. Khi một lời gọi từ một màn hình đi qua nhiều dịch vụ và sự kiện bất đồng bộ, thành viên mới khó nắm được toàn bộ ranh giới trách nhiệm nếu chỉ nhìn vào môi trường thực thi.

Bối cảnh thứ hai là thực tế người đọc và mục đích của tài liệu khác nhau. Ban lãnh đạo muốn biết hệ thống hỗ trợ nghiệp vụ nào và kết nối với đối tác bên ngoài nào. Người vận hành cần miền sự cố, nút triển khai, vị trí giám sát và đường khôi phục. Nhà phát triển phải xác nhận trách nhiệm module, giao diện, luồng dữ liệu và phạm vi ảnh hưởng của thay đổi. Nếu áp đặt một bản thiết kế chi tiết duy nhất cho tất cả, thông tin cốt lõi của từng nhóm người đọc sẽ bị chôn vùi.

Bối cảnh thứ ba là sự lãng quên căn cứ thiết kế. Ở giai đoạn đầu dự án, nhiều phương án đã được xem xét nhưng mã nguồn cuối cùng chỉ còn lại kết quả được chọn. Vài năm sau, người phụ trách mới có thể lặp lại cùng cuộc tranh luận mà không biết các ràng buộc hiện tại, hoặc hiểu lầm một quyết định có lý do về hiệu năng·quy định·vận hành chỉ là mã cũ kỹ. ADR không lưu kết quả lựa chọn mà lưu quá trình hình thành lựa chọn và tiêu chí phán đoán tại thời điểm đó.

B. Mục tiêu và phạm vi áp dụng

Mục tiêu của tài liệu hóa không phải là sao chép toàn bộ mã thành hình vẽ. Mục tiêu thứ nhất là nhanh chóng chia sẻ ranh giới và trách nhiệm của hệ thống. Mục tiêu thứ hai là giải thích mối quan hệ giữa các yêu cầu thuộc tính chất lượng quan trọng và các lựa chọn cấu trúc. Mục tiêu thứ ba là giảm thời gian phân tích ảnh hưởng khi thay đổi và thời gian hội nhập (onboarding). Mục tiêu thứ tư là quản lý đồng thời nợ thiết kế và nợ tài liệu.

Phạm vi áp dụng không chỉ là giai đoạn thiết kế hệ thống mới mà còn cả kỹ nghệ ngược hệ thống hiện có. Dự án mới xuất phát từ mục tiêu nghiệp vụ và kịch bản chất lượng để đồng thời tạo các view C4 và ADR. Với hệ thống kế thừa (legacy), trước hết quan sát hành vi hiện tại để lập view Context·Container, đánh dấu phần chưa chắc chắn là “cần xác nhận”, rồi bổ sung dần cùng với công việc thay đổi.

Để tài liệu thực sự được dùng trong vận hành, nó phải được review trong cùng kho với mã nguồn. Ví dụ, có thể đặt mã nguồn sơ đồ và phần giải thích trong docs/architecture/c4/, và lưu các ADR đánh số tăng dần trong docs/architecture/adr/. Ở tổ chức lớn, cách giữ các nguyên tắc chung trong một danh mục tập trung nhưng để cấu trúc và quyết định của từng dịch vụ trong kho của dịch vụ đó tạo được sự cân bằng giữa khả năng truy vết và quyền sở hữu.

2. Các tầng và nguyên tắc biểu diễn của mô hình C4

Mô hình C4 chia kiến trúc phần mềm thành bốn mức trừu tượng cốt lõi. System Context thể hiện quan hệ giữa hệ thống với con người·hệ thống bên ngoài, Container thể hiện các đơn vị thực thi·triển khai bên trong hệ thống, Component thể hiện trách nhiệm logic bên trong một container, và Code thể hiện cấu trúc hiện thực của component. Ngoài ra có thể dùng bổ trợ Dynamic diagram mô tả trình tự của một kịch bản cụ thể và Deployment diagram cho thấy cách bố trí hạ tầng của container.

flowchart TB
    A[Mối quan tâm của bên liên quan\nCâu hỏi nghiệp vụ·chất lượng·vận hành] --> B[System Context\nRanh giới hệ thống và quan hệ bên ngoài]
    B --> C[Container\nĐơn vị ứng dụng·API·DB·thông điệp]
    C --> D[Component\nPhân rã trách nhiệm trong container]
    D --> E[Code\nCấu trúc lớp·module·hàm]
    C --> F[Dynamic\nLuồng runtime của kịch bản cụ thể]
    C --> G[Deployment\nNút thực thi·môi trường·bố trí]
    E --> H[Mã nguồn·tài liệu sinh tự động]
    F --> I[Khả năng quan sát·hiệu năng·kịch bản sự cố]
    G --> J[Ranh giới bảo mật·tính sẵn sàng·khôi phục]

Các tầng này không đồng nhất với sơ đồ tổ chức chính thức hay số lượng microservice. Container không nhất thiết chỉ là tiến trình chạy bằng công nghệ container, mà là đơn vị được thực thi hoặc triển khai độc lập như một ứng dụng·dịch vụ·kho dữ liệu. Vì vậy, hệ thống nguyên khối (monolithic) cũng có thể được biểu diễn thành một Container, và các module bên trong nó được mô tả như Component.

A. Sơ đồ System Context

Sơ đồ System Context là điểm khởi đầu của tài liệu. Đặt hệ thống quan tâm thành một hộp trung tâm, và bố trí xung quanh các vai trò người dùng và hệ thống bên ngoài tương tác với nó. Ở mức này không đưa vào lớp nội bộ hay framework, mà mô tả bằng câu văn dễ hiểu trách nhiệm của hệ thống, quan hệ bên ngoài và các luồng dữ liệu·nghiệp vụ chính.

Một view Context tốt cho thấy đồng thời “hệ thống này làm gì” và “không làm gì”. Ví dụ, hệ thống đặt hàng mua sắm có thể kết nối với khách hàng·nhân viên tư vấn·cổng thanh toán·đối tác giao hàng, nhưng phải ghi rõ bản thân việc phê duyệt thanh toán là trách nhiệm của hệ thống thanh toán bên ngoài. Nếu không làm rõ ranh giới, trách nhiệm sự cố, trách nhiệm xử lý thông tin cá nhân và trách nhiệm thay đổi giao diện sẽ bị phân bổ sai.

Trong thực tế, trước hết phỏng vấn để lập danh sách hành trình người dùng và các liên kết bên ngoài, rồi ghi cho mỗi quan hệ mục đích·hướng·thông tin chính·ranh giới tin cậy. Thay vì chỉ vẽ một đường “gọi”, hãy viết ý nghĩa quan hệ như “hệ thống đặt hàng gửi yêu cầu phê duyệt thanh toán và nhận kết quả phê duyệt”. Nhờ vậy, người không chuyên kỹ thuật cũng có thể review phạm vi nghiệp vụ, còn người phụ trách bảo mật có thể đặt câu hỏi về yêu cầu xác thực·mã hóa tại ranh giới bên ngoài.

B. Sơ đồ Container

Sơ đồ Container cho thấy các đơn vị thực thi chính bên trong hệ thống và mang lại hiệu quả trên đầu tư cao nhất ở phần lớn các nhóm. Nó thể hiện các phần tử được thực thi·triển khai·mở rộng độc lập như ứng dụng web, ứng dụng di động, dịch vụ API, tác vụ batch, message broker, cơ sở dữ liệu quan hệ, kho lưu trữ đối tượng. Mỗi phần tử phải ghi kèm trách nhiệm, lựa chọn công nghệ, phương thức giao tiếp và tính chất dữ liệu lưu trữ.

Lý do tách Container không đơn thuần là để tăng số dịch vụ. Một đơn vị riêng chỉ có ý nghĩa khi chu kỳ thay đổi, cô lập sự cố, nhu cầu mở rộng, quyền sở hữu bảo mật·dữ liệu và phạm vi trách nhiệm của nhóm khác nhau. Ngược lại, nếu chỉ tăng thêm lời gọi mạng trong khi dữ liệu và việc triển khai vẫn gắn chặt với nhau, việc chia thành nhiều dịch vụ về hình thức có thể làm tăng độ phức tạp vận hành.

Xem xét ranh giới Container bằng các câu hỏi sau. Thứ nhất, phần tử này có thể được triển khai hoặc rollback độc lập không. Thứ hai, chủ sở hữu của dữ liệu và bất biến (invariant) có rõ ràng không. Thứ ba, có lý do để chấp nhận độ trễ gọi và sự lan truyền sự cố không. Thứ tư, ranh giới nghiệp vụ của nhóm và luồng phê duyệt thay đổi có khớp với cấu trúc không. Việc tách mà không trả lời được các câu hỏi này nhiều khả năng là “phân tán vì phân tán”.

C. Sơ đồ Component và Code

Sơ đồ Component cho thấy các component logic chính và trách nhiệm bên trong một Container cụ thể. Ví dụ, bên trong API đặt hàng có thể có bộ kiểm tra đơn hàng, dịch vụ chính sách giá, adapter đặt giữ tồn kho, bộ điều phối thanh toán và bộ phát sự kiện. Mỗi component phải có một trách nhiệm và hướng phụ thuộc rõ ràng, đồng thời phải phân biệt giao diện bên ngoài với điểm chuyển đổi dữ liệu.

Mức Component không được áp dụng một cách máy móc cho mọi container. Nếu cấu trúc bên trong đơn giản hoặc bản thân mã đã đủ giải thích, tốt hơn là không tạo tài liệu. Ngược lại, với những vùng có ảnh hưởng thay đổi lớn và thường xuyên có nhân sự mới tiếp cận, như module thanh toán·phân quyền·quyết toán có quy tắc phức tạp, view Component có giá trị cao.

Mức Code biểu diễn chi tiết hiện thực như lớp·interface·package·hàm. Nếu vẽ tay toàn bộ mã thì tài liệu sẽ nhanh lỗi thời, vì vậy hãy sinh tự động bằng IDE hoặc công cụ phân tích tĩnh, hoặc chỉ ghi hạn chế những phần thực sự cần như thuật toán·mô hình miền cốt lõi. Nếu lớp được vẽ trong tài liệu khác với mã thực tế, người đọc sẽ mất niềm tin vào mọi tài liệu, nên có thể mạnh dạn lược bỏ view Code khó tự động hóa.

D. Sơ đồ Dynamic·Deployment

Sơ đồ Dynamic mô tả theo trình tự có đánh số một kịch bản khó hiểu nếu chỉ dựa vào quan hệ kết nối tĩnh. Nó có thể cho thấy luồng “tạo đơn hàng” trong đó API đặt giữ tồn kho, yêu cầu thanh toán rồi phát sự kiện, hoặc cách thử lại·xử lý bù (compensation) khi có sự cố. Khi tách luồng bình thường và luồng thất bại theo từng kịch bản, việc thảo luận về timeout, thông điệp trùng lặp, tính lũy đẳng (idempotency) và ranh giới giao dịch trở nên dễ dàng hơn.

Sơ đồ Deployment thể hiện Container được bố trí trên nút thực thi·tài nguyên đám mây·vùng khả dụng (availability zone) nào. Nó biểu thị sự khác biệt giữa môi trường phát triển·staging·vận hành, ranh giới mạng công cộng·riêng tư, vị trí quản lý bí mật (secret), các nút nhân bản và chuyển đổi dự phòng. Khi liên kết cấu trúc ứng dụng với cấu trúc hạ tầng, có thể truy vết “vì sao cùng một mã nhưng chỉ lỗi ở môi trường vận hành” và “sự cố của một nút ảnh hưởng đến dịch vụ nào”.

sequenceDiagram
    actor C as Khách hàng
    participant W as Ứng dụng Web
    participant O as API đặt hàng
    participant I as Dịch vụ tồn kho
    participant P as Adapter thanh toán
    participant B as Message broker
    participant N as Dịch vụ thông báo
    C->>W: Gửi đơn hàng
    W->>O: Yêu cầu tạo đơn hàng
    O->>I: Đặt giữ tồn kho (khóa lũy đẳng)
    I-->>O: Kết quả đặt giữ
    O->>P: Yêu cầu phê duyệt thanh toán
    P-->>O: Phê duyệt hoặc từ chối
    O->>B: Phát sự kiện OrderCreated
    B->>N: Tiêu thụ thông báo
    N-->>C: Thông báo trạng thái đơn hàng
    O-->>W: Mã đơn hàng·trạng thái

Trong luồng động, nhóm cần quy ước hướng mũi tên biểu thị hướng gọi, còn đường nét đứt hoặc ký hiệu riêng biểu thị truyền bất đồng bộ. Đừng chỉ dựa vào hình dạng đường nối, mà hãy ghi kèm bằng câu văn cho mỗi quan hệ: đồng bộ·bất đồng bộ, thử lại, timeout, hợp đồng dữ liệu. Hình vẽ là bản đồ để hiểu nhanh, còn quy tắc vận hành phải được kiểm chứng bằng phần giải thích cùng kiểm thử·cấu hình.

3. Cấu trúc ADR và quản lý quyết định

ADR là tài liệu ngắn ghi lại một quyết định có ảnh hưởng lâu dài đến kiến trúc. Nếu biến ticket hiện thực chức năng hay mọi lần review mã thành ADR, tín hiệu của các quyết định quan trọng sẽ bị chìm lấp. Ngược lại, những lựa chọn khó đảo ngược và ảnh hưởng đến nhiều thuộc tính chất lượng như kho dữ liệu, phương thức xác thực, mẫu giao tiếp, chiến lược triển khai, nơi lưu giữ thông tin cá nhân được xem là ứng viên ADR.

flowchart LR
    A[Vấn đề·yêu cầu chất lượng·ràng buộc] --> B[Khám phá phương án]
    B --> C[Đề xuất ADR\nTrạng thái: Proposed]
    C --> D[Review bởi các bên liên quan]
    D -->|Đồng thuận| E[Phê duyệt ADR\nTrạng thái: Accepted]
    D -->|Cần kiểm chứng thêm| F[Thử nghiệm·PoC·kiểm thử tải]
    F --> B
    E --> G[Phản ánh vào view C4·mã·chính sách vận hành]
    G --> H[Giám sát·nhìn lại]
    H -->|Tiền đề thay đổi| I[Viết ADR mới]
    I --> J[ADR cũ Superseded]

A. Context và định nghĩa vấn đề

Phần Context nên ghi một cách trung lập các sự kiện và các lực tác động tại thời điểm ra quyết định, thay vì những diễn đạt biện minh trước cho kết luận. Cần bao gồm mục tiêu kinh doanh, tải dự kiến, yêu cầu quy định, năng lực nhóm, tiến độ, ràng buộc của hệ thống hiện có và đặc tính dữ liệu. Những câu như “vì là công nghệ mới nhất” không trở thành tiêu chí kiểm chứng, nên cần cụ thể hóa muốn cải thiện thuộc tính chất lượng nào và điều kiện vận hành nào.

Ví dụ, Context của quyết định “chuyển sự kiện đơn hàng qua message broker” ghi rằng thời gian xử lý phê duyệt thanh toán và thông báo khác nhau, sự cố của nhà cung cấp thông báo không được lan sang việc tạo đơn hàng, và cần thiết kế consumer chịu được sự kiện trùng lặp. Viết như vậy, về sau khi quy mô lưu lượng hay yêu cầu thông báo thay đổi, có thể đánh giá liệu tiền đề của quyết định cũ còn hiệu lực hay không.

B. Decision và so sánh phương án

Decision được viết bằng câu chủ động “chúng tôi chọn điều gì”. Không chỉ ghi tên công nghệ đã chọn mà còn bao gồm phạm vi áp dụng, nguyên tắc giao diện, điều kiện ngoại lệ và kế hoạch chuyển đổi. Ví dụ, nêu rõ ranh giới như “giữ lời gọi đồng bộ giữa tạo đơn hàng và phê duyệt thanh toán, nhưng tách việc thông báo·cập nhật chỉ mục tìm kiếm thành sự kiện OrderCreated, và consumer sự kiện bảo đảm tính lũy đẳng theo mã đơn hàng”.

Cần xem xét ít nhất hai phương án và để lại lý do không chọn. So sánh phương án không phải là liệt kê danh sách chức năng, mà phải giải thích ảnh hưởng đến thuộc tính chất lượng trong Context hiện tại và chi phí tổ chức phải gánh chịu. Bảng sau là ví dụ lựa chọn phương thức truyền thông điệp.

Phương án Ưu điểm Gánh nặng·rủi ro Nhận định áp dụng
Toàn bộ gọi REST đồng bộ Luồng trực quan, xác nhận kết quả ngay Tăng lan truyền sự cố và độ kết dính, giới hạn mở rộng lúc cao điểm Các bước cốt lõi cần nhất quán tức thời mạnh
Toàn bộ sự kiện bất đồng bộ Cải thiện độ kết dính và khả năng mở rộng độc lập Cần quản lý độ trễ·trùng lặp·thứ tự·khả năng truy vết Xử lý hậu kỳ và luồng sự kiện quy mô lớn
Kết hợp cốt lõi đồng bộ·phụ trợ bất đồng bộ Cân bằng giữa phản hồi người dùng và cô lập sự cố Cần quy tắc vận hành·quan sát cho cả hai mô hình Chiến lược phổ biến tách đặt hàng·thanh toán khỏi thông báo

Việc chọn “kết hợp” trong bảng không có nghĩa lúc nào cũng tối ưu. Với bước mà người dùng cần biết ngay thành công hay không như phê duyệt thanh toán, để ở luồng đồng bộ có thể giúp xử lý lỗi rõ ràng hơn. Ngược lại, tác vụ chấp nhận được độ trễ vài giây như gửi email có thể được bất đồng bộ hóa để độ trễ của nhà cung cấp bên ngoài không chặn phản hồi của API đặt hàng. Do đó, kết quả lựa chọn phải dựa trên độ trễ cho phép của nghiệp vụ và cách bù đắp khi thất bại.

C. Consequences và quản lý trạng thái

Phần Consequences ghi đầy đủ các hệ quả tích cực·tiêu cực·trung tính. Cấu trúc dựa trên thông điệp làm giảm độ kết dính giữa các dịch vụ và hỗ trợ mở rộng độc lập, nhưng phải quản lý mới các vấn đề nhất quán cuối cùng (eventual consistency)·tiêu thụ trùng lặp·đảo thứ tự·lan truyền mã truy vết. Nếu che giấu hệ quả tiêu cực, ADR sẽ thành tài liệu quảng bá và người vận hành tương lai không lường trước được chi phí thực tế.

Trạng thái ADR có vòng đời rõ ràng, tối thiểu gồm Proposed, Accepted, Deprecated, Superseded. Nếu lặng lẽ sửa tài liệu Accepted về sau, bản ghi phán đoán lúc đó và tri thức hiện tại sẽ bị trộn lẫn. Khi đảo ngược quyết định, hãy viết ADR mới và để lại trong tài liệu cũ số hiệu tài liệu thay thế cùng lý do chuyển đổi.

Cấu trúc C4 đã thay đổi được review trong cùng gói thay đổi với ADR liên quan. Ví dụ, pull request thay thế cơ sở dữ liệu phải bao gồm đồng thời tên công nghệ trong view Container, cách bố trí trong view Deployment, chiến lược di chuyển dữ liệu và việc thay đổi trạng thái ADR tương ứng. Nếu tài liệu và mã đi theo các bản phát hành tách rời, sẽ xuất hiện cấu trúc ma như dịch vụ có trong hình vẽ nhưng thực tế không được gọi.

D. Ví dụ mẫu ADR

Mẫu tối thiểu có thể dùng trong thực tế như sau.

# ADR-0012: Tách xử lý hậu kỳ đơn hàng theo hướng sự kiện

- Trạng thái: Accepted
- Ngày: 2026-09-18
- C4 liên quan: Container - Order API, Notification Service

## Context
Cần tách thời gian phản hồi tạo đơn hàng khỏi độ trễ bên ngoài của nhà cung cấp thông báo.

## Decision
API đặt hàng phát sự kiện OrderCreated sau khi hoàn tất tạo đơn hàng.
Consumer thông báo dùng mã đơn hàng làm khóa lũy đẳng.

## Alternatives
Đã xem xét phương án gọi đồng bộ mọi xử lý hậu kỳ và phương án polling theo batch.

## Consequences
Phản hồi đơn hàng ổn định hơn nhưng phải vận hành nhất quán cuối cùng, xử lý lại và truy vết sự kiện.

## Follow-up
Giám sát tỷ lệ tiêu thụ trùng lặp và độ trễ thông báo, diễn tập xử lý lại mỗi quý.

Mục đích của mẫu không phải là áp đặt hình thức một cách cứng nhắc, mà là để không bỏ sót bối cảnh và kết quả của quyết định. Nếu nhóm nhỏ, có thể bắt đầu chỉ với Status·Context·Decision·Consequences. Với ngành chịu quản lý chặt hoặc nền tảng do nhiều nhóm cùng vận hành, bổ sung người ra quyết định, người được tham vấn, các dịch vụ bị ảnh hưởng, chỉ số kiểm chứng và điều kiện hết hạn·xem xét lại.

4. Quy trình vận hành tích hợp C4 và ADR

Vận hành tích hợp không theo thứ tự “vẽ hình xong rồi viết tài liệu riêng”, mà là một quá trình tuần hoàn kết nối câu hỏi·quyết định·kiểm chứng. Trước hết, dùng view Context để thống nhất ranh giới hệ thống và quan hệ bên ngoài, rồi dùng view Container để xem xét trách nhiệm·triển khai·quyền sở hữu dữ liệu. Khi phát hiện xung đột thuộc tính chất lượng hoặc lựa chọn khó đảo ngược, đề xuất ADR và sau khi được phê duyệt thì phản ánh vào các phần tử C4 liên quan và phần hiện thực.

flowchart TB
    A[Mục tiêu kinh doanh·câu hỏi của bên liên quan] --> B[Lập view Context]
    B --> C[Lập view Container·triển khai]
    C --> D{Có phải lựa chọn cấu trúc quan trọng?}
    D -->|Không| E[Giải thích·review mã]
    D -->|Có| F[Viết ADR·so sánh phương án]
    F --> G[Kiểm chứng PoC·bảo mật·hiệu năng]
    G --> H[Phê duyệt hoặc xem xét lại ADR]
    H --> I[Thay đổi đồng thời C4·mã·IaC]
    I --> J[CI kiểm tra liên kết tài liệu·render]
    J --> K[Chỉ số vận hành·nhìn lại·cập nhật tài liệu]
    K --> C

A. Soạn thảo và review tài liệu

Trong workshop thiết kế, không vẽ view Component chi tiết ngay từ đầu. Trước hết xác nhận Context có người dùng và liên kết bên ngoài, rồi ánh xạ trách nhiệm nghiệp vụ và kịch bản chất lượng lên ranh giới Container. Sau đó chỉ mở rộng sang view Component và Dynamic cho những phần tử phát sinh vấn đề như cô lập sự cố·mở rộng·nhất quán dữ liệu. Trình tự này giảm việc chi tiết hóa không cần thiết và thời gian họp.

Người review phải xem xét ý nghĩa trước ký pháp. Kiểm tra chủ thể·đối tượng của hệ thống có đúng không, chủ sở hữu dữ liệu đã được thể hiện chưa, ranh giới tin cậy và đường lan sự cố có bị bỏ sót không, và quyết định của từng ADR có khớp với mã·cấu hình triển khai hiện tại không. Nếu chỉ tốn thời gian cho vị trí hay màu sắc của hình vẽ, tài liệu có đẹp lên nhưng rủi ro thiết kế không giảm.

B. Docs-as-Code và tự động hóa

Khi lưu mã nguồn sơ đồ và ADR trong Git, có thể dùng chung nhánh·pull request·review·lịch sử thay đổi như với mã. Các biểu diễn dạng văn bản như Mermaid, PlantUML, Structurizr DSL có lợi cho tự động hóa render và tìm kiếm, nhưng cần cân nhắc cú pháp và độ ổn định đầu ra của công cụ mà nhóm chọn. Điều quan trọng hơn công cụ là chi phí thấp để người thực sự thay đổi có thể sửa tài liệu cùng lúc.

Trong CI có thể kiểm tra cú pháp Mermaid, tính hợp lệ của liên kết, trùng số ADR, liên kết Superseded và phần mô tả bắt buộc của các phần tử C4. Lưu HTML·PNG sinh ra trong pipeline triển khai như artifact, và hiển thị liên kết ADR liên quan trên màn hình phê duyệt thay đổi vận hành, sẽ giúp tài liệu không kết thúc như một sản phẩm dùng một lần. Tuy nhiên, view Code sinh tự động dù mới nhất cũng không giải thích được ý đồ kiến trúc, nên phần diễn giải cấu trúc phải do con người duy trì.

C. Chỉ số chất lượng tài liệu

Hiệu quả của tài liệu hóa được đo không phải bằng số tệp tài liệu, mà bằng tốc độ trả lời câu hỏi và mức độ an toàn của thay đổi. Ví dụ, có thể theo dõi thời gian nhà phát triển mới nắm được ranh giới và luồng triển khai của hệ thống cốt lõi, thời gian tìm phụ thuộc liên quan và nhóm phụ trách khi ứng phó sự cố, và tỷ lệ quyết định quan trọng có liên kết ADR. Nếu tài liệu nhiều lên mà thời gian onboarding không giảm, nghĩa là người đọc đang bị cung cấp quá nhiều thông tin chi tiết không cần thiết hoặc độ tin cậy của nội dung thấp.

Tiêu chí vận hành cụ thể được xác định theo từng hệ thống. View Container của dịch vụ cốt lõi được xem xét trước các thay đổi triển khai lớn, và ADR được viết cho mỗi quyết định cấu trúc như kho dữ liệu·xác thực·giao thức giao tiếp. Lỗi không nhất quán giữa sơ đồ và mã, tỷ lệ ADR lỗi thời, lỗi liên kết, phụ thuộc bị bỏ sót trong sự cố vận hành cũng có thể được quản lý như chỉ số nợ tài liệu.

5. So sánh và ví dụ thực tế

A. So sánh C4 với UML·sơ đồ cấu trúc khổng lồ duy nhất

UML cung cấp nhiều loại mô hình và ký pháp tinh vi, mạnh ở việc biểu diễn chặt chẽ một thiết kế·hành vi cụ thể. C4 dùng tập hợp giới hạn các khái niệm cốt lõi và tầng lớp, tập trung vào việc tăng tốc giao tiếp giữa nhóm và các bên liên quan không chuyên kỹ thuật. Vì vậy, thay vì cho rằng chỉ một trong hai là đúng, cách kết hợp thực tế là dùng C4 để lập bản đồ tổng thể và bổ sung bằng UML hoặc mô hình mã cho các thuật toán nội bộ phức tạp.

Sơ đồ cấu trúc khổng lồ duy nhất có thể chứa nhiều thông tin trên một trang, nhưng mối quan tâm của từng nhóm người đọc và chu kỳ thay đổi bị trộn lẫn. Các view của C4 cung cấp cùng một mô hình ở các mức phóng to khác nhau để kiểm soát lượng thông tin. Đổi lại, phải giữ nhất quán tên phần tử·quan hệ·trách nhiệm giữa các view, nên cần có quản trị tài liệu.

Phân loại Mô hình C4 Tài liệu lấy UML làm trung tâm Sơ đồ cấu trúc khổng lồ duy nhất
Mục đích cốt lõi Hiểu kiến trúc theo từng người đọc Biểu diễn chính xác cấu trúc·hành vi thiết kế Hiển thị toàn bộ quan hệ trong một lần
Trừu tượng hóa Context→Container→Component→Code Đa dạng theo loại sơ đồ Dễ bị trộn lẫn trên một trang
Ưu điểm Thuận lợi cho giải thích·phóng to·onboarding Mô hình hóa hình thức và thiết kế chi tiết Tổng quan nhanh ở giai đoạn đầu
Rủi ro chính Mơ hồ nếu thiếu quy tắc quan hệ Hình thức quá mức và chi phí soạn thảo Giảm khả năng đọc do phức tạp
Biện pháp bổ sung Phần giải thích·ADR·kiểm chứng tự động Chọn lọc view theo người đọc và phần cốt lõi Phân tầng, chia nhỏ và liên kết

B. Ví dụ nền tảng đặt hàng thương mại điện tử

Trong nền tảng thương mại điện tử, view Context phân biệt khách hàng·người vận hành·hệ thống đặt hàng·cổng thanh toán·đối tác giao hàng·nhà cung cấp thông báo khách hàng. View Container mở rộng thành ứng dụng web khách hàng, API đặt hàng, dịch vụ tồn kho, adapter thanh toán, DB đơn hàng, event broker và dịch vụ thông báo. Chỉ với cấu trúc này đã có thể thảo luận sự cố của nhà cung cấp thanh toán có cùng loại với sự cố tra cứu đơn hàng hay không, và nhà cung cấp thông báo có nằm trên luồng cốt lõi của đơn hàng hay không.

Lựa chọn “tách thông báo thành sự kiện” được lưu lại bằng ADR. Context ghi độ trễ mục tiêu của phản hồi đặt hàng thành công, độ trễ cho phép của thông báo, tỷ lệ lỗi của nhà cung cấp bên ngoài và giới hạn thử lại. Decision nêu rõ phiên bản lược đồ sự kiện, khóa xử lý trùng lặp, hàng đợi thất bại và trách nhiệm xử lý lại. Consequences bao gồm việc người dùng có thể đặt hàng thành công nhưng nhận thông báo muộn, và người vận hành phải giám sát hàng đợi xử lý lại.

Ví dụ, giả sử vào giờ cao điểm API đặt hàng phải xử lý 2,000 đơn mỗi giây, còn API thông báo có độ trễ trung bình 1 giây và tối đa 30 giây khi có sự cố. Nếu để thông báo ở dạng gọi đồng bộ, độ trễ đuôi (tail latency) của phản hồi đặt hàng sẽ tăng do API bên ngoài, và khi tính cả thử lại, thread·connection pool có thể bị cạn kiệt. Tách thành sự kiện giúp giới hạn độ trễ trên luồng đặt hàng, nhưng cần xem xét thiết kế bổ sung như Transactional Outbox để bảo đảm tính nguyên tử giữa việc phát sự kiện thành công và giao dịch DB.

C. Tài liệu hóa trong hệ thống tài chính·công

Hệ thống tài chính·công phải giải thích đồng thời thông tin cá nhân, vết kiểm toán, khôi phục sự cố và phụ thuộc vào nhà cung cấp. View Context thể hiện các chủ thể như công dân·nhân viên·cơ quan·tổ chức xác thực bên ngoài, còn view Deployment thể hiện phân tách mạng·đoạn mã hóa·site dự phòng. ADR ghi lại phương tiện xác thực và cách quản lý khóa, thời hạn lưu giữ dữ liệu, phạm vi sử dụng đám mây bên ngoài và trách nhiệm về bằng chứng kiểm toán.

Trong môi trường này, cách tiếp cận “bổ sung tài liệu sau” có thể nguy hiểm. Các quyết định liên quan đến xác thực·lưu trữ thông tin cá nhân·chuyển dữ liệu ra nước ngoài phải được xem xét cùng người phụ trách bảo mật·pháp chế·kiểm toán trước khi hiện thực, và ghi lại căn cứ quyết định cùng ngày hết hạn của phê duyệt ngoại lệ. Tuy nhiên, bản thân ADR không tự động bảo đảm tuân thủ quy định, nên phải được dùng cùng với chính sách, bằng chứng kiểm thử và nhật ký truy cập.

6. Chuyên sâu: Tính bền vững của tri thức kiến trúc và quản lý thay đổi

Sự kết hợp C4 và ADR có thể phát triển từ tài liệu mô tả cấu trúc hiện tại thành đồ thị tri thức kiến trúc. Liên kết các phần tử C4 với nhóm sở hữu, thuộc tính chất lượng, dashboard vận hành, hợp đồng API, ADR liên quan, và liên kết ngược từ ADR đến các phần tử bị ảnh hưởng và chỉ số kiểm chứng. Khi đó, lúc thay thế một kho dữ liệu cụ thể, có thể tìm phạm vi ảnh hưởng tới cả dịch vụ liên quan·nút triển khai·biện pháp kiểm soát bảo mật·tiền đề của quyết định.

Kiến trúc bị xói mòn theo thời gian. Nếu nhóm thêm các liên kết tạm thời mà không cập nhật tài liệu, sẽ xuất hiện khoảng cách giữa cấu trúc thực tế và cấu trúc dự định. Để ngăn điều này, cần đưa kiểm tra tính phù hợp kiến trúc (architecture fitness) cho các quan hệ C4 quan trọng vào CI, và định kỳ xem xét lại tiền đề của ADR cùng các chỉ số SLO·chi phí·bảo mật. Việc kiểm tra không chỉ hỏi “tài liệu có giống mã không” mà còn phải hỏi “lựa chọn hiện tại có còn phù hợp mục tiêu kinh doanh không”.

Ví dụ, nếu quy mô dữ liệu lớn hơn dự kiến ban đầu khiến việc mở rộng một DB đơn lẻ chạm giới hạn, các con số trong Context của ADR cũ có thể không còn đúng. Khi đó, thay vì sửa ADR cũ và xóa bản ghi quá khứ, hãy viết ADR mới khảo sát các phương án như sharding·bản sao đọc·tách kho phân tích. Review cùng lúc view Container·Deployment mới và kết quả kiểm chứng di chuyển dữ liệu, rồi đánh dấu ADR trước là Superseded, sẽ bảo toàn được cả tính liên tục của phán đoán lẫn lý do thay đổi.

Dù công cụ lập trình AI và sinh tài liệu tự động lan rộng, trách nhiệm ra quyết định không được tự động hóa. Có thể trích đồ thị lời gọi từ mã để tạo bản nháp Component, nhưng việc đặt một ranh giới cụ thể thuộc quyền sở hữu nhóm nào, hệ thống nào lưu giữ thông tin cá nhân, chấp nhận điểm cân bằng nào giữa hiệu năng và chi phí là phán đoán của tổ chức. Kết quả sinh tự động phải ghi thời điểm sinh và phạm vi phân tích, và chỉ những kết quả đã qua review của con người và phê duyệt ADR mới được coi là kiến trúc chính thức.

7. Các điểm cần cân nhắc và hàm ý

A. Tài liệu hóa tối thiểu dựa trên mục đích

Nếu bắt buộc mọi hệ thống có cùng số lượng sơ đồ và ADR, tài liệu sẽ biến thành công việc hình thức. Phải chọn view cần thiết dựa trên câu hỏi của các bên liên quan cốt lõi, rủi ro thay đổi, ảnh hưởng sự cố và nghĩa vụ pháp lý. Cách tiếp cận tăng dần — bắt đầu từ Context và Container tối thiểu, chỉ bổ sung Component·Dynamic·Deployment cho vùng phức tạp — nâng cao tính bền vững.

B. Phân biệt trạng thái hiện tại và trạng thái mục tiêu

Tài liệu thiết kế không được trộn lẫn hiện trạng (As-Is), mục tiêu đã được phê duyệt (To-Be) và phương án đang thử nghiệm. Mỗi view C4 phải ghi trạng thái và commit·môi trường tham chiếu, đồng thời làm rõ trạng thái và phạm vi áp dụng của ADR. Đặc biệt trong quá trình di chuyển (migration), phải biểu diễn quan hệ đồng bộ dữ liệu giữa hệ thống cũ·mới bằng view Deployment·Dynamic để người vận hành biết nên tin cậy luồng nào.

C. Liên kết thuộc tính chất lượng với kiểm chứng

Lựa chọn kiến trúc không nên dừng ở mức trừu tượng như “có khả năng mở rộng”, mà phải gắn với kịch bản đo lường được. Ghi vào ADR các chỉ số kiểm chứng như thời gian phản hồi, thông lượng, thời gian khôi phục, độ tươi dữ liệu, lưu giữ nhật ký kiểm toán, thời gian xử lý lỗ hổng, và liên kết kết quả PoC·kiểm thử tải·kiểm thử bảo mật. Tuyên bố chất lượng chưa được kiểm chứng phải được coi là giả thuyết chứ không phải ý đồ thiết kế.

D. Bảo mật·thông tin cá nhân và trách nhiệm thay đổi

View Context và Deployment của C4 phải thể hiện ranh giới tin cậy, điểm xác thực·ủy quyền, đoạn mã hóa và luồng thông tin cá nhân. ADR ghi lại tối thiểu hóa dữ liệu, chủ thể truy cập, lưu giữ·xóa, xoay vòng khóa và trách nhiệm ứng phó sự cố cùng với quyết định cấu trúc. Nếu cấu trúc thay đổi sau khi review bảo mật đã xong, phải xem xét lại ADR và mô hình mối đe dọa liên quan, và tránh kiểu tuân thủ hình thức chỉ cập nhật tài liệu mà không áp dụng biện pháp kiểm soát.

E. Quyền sở hữu tài liệu và điều kiện kích hoạt cập nhật

Tài liệu phải ghi nhóm phụ trách và ngày review gần nhất, và yêu cầu cập nhật khi đơn vị triển khai·giao diện·kho dữ liệu·ranh giới xác thực thay đổi. Chỉ với quy tắc “mỗi quý vẽ lại toàn bộ” thì không ngăn được sự không nhất quán ngay sau thay đổi, nên đưa việc cập nhật tài liệu vào review mã và checklist phát hành sẽ hiệu quả hơn. Thay vì wiki trung tâm không có chủ sở hữu, nên đặt tài liệu trong kho của nhóm vận hành dịch vụ, và cung cấp tiêu chuẩn chung của tổ chức dưới dạng mẫu có thể tái sử dụng.

F. Triển vọng từ góc nhìn Kỹ sư chuyên nghiệp

Trong tương lai, tài liệu kiến trúc phải trở thành tài sản tri thức có thể kiểm chứng, gắn với mã·IaC·khả năng quan sát·chính sách, thay vì hình ảnh tĩnh. Tuy nhiên, mức tự động hóa càng cao thì càng phải phân biệt “hình vẽ đã được sinh ra” với “ý đồ và đánh đổi đã được đồng thuận”. Kỹ sư chuyên nghiệp phải đảm nhận vai trò thiết kế và tài liệu hóa mối liên kết giữa mục tiêu kinh doanh, thuộc tính chất lượng, vận hành tổ chức, quy định và quản lý thay đổi, hơn là việc chọn ký pháp.

Tài liệu tham khảo


Tóm tắt một câu: Dùng C4 để cho thấy “cái gì” của kiến trúc ở mức phù hợp từng người đọc và dùng ADR để ghi lại “vì sao” cùng các đánh đổi, tạo nên tài liệu thiết kế sống, cùng tiến hóa với cấu trúc·mã·vận hành.