Kiểm soát chất lượng
Definition of Done
Điều kiện một hạng mục phải thoả trước khi được gọi là xong — khác nhau theo loại hạng mục và theo module, có người ký tên, và ở quy mô 500.000 người dùng thì "xong" nghĩa là đã quan sát được trên dữ liệu thật chứ không phải đã merge.
Nội dung bài
Thuật ngữ trong bài (33)
- accessibility · khả năng tiếp cận
- empty state · trạng thái rỗng
- font scale · mức phóng chữ
- acceptance criteria · tiêu chí nghiệm thu
- definition of done · định nghĩa hoàn thành
- quality gate · cổng chất lượng
- retro · họp nhìn lại
- waiver · miễn trừ có kiểm soát
- build · bản dựng
- CI · tích hợp liên tục
- code review · soát mã
- linter · máy soát mã
- merge · gộp nhánh
- pull request · yêu cầu gộp mã
- bug · lỗi
- coverage · độ phủ test
- device matrix · ma trận thiết bị
- integration test · kiểm thử tích hợp
- regression · lỗi tái phát
- unit test · kiểm thử đơn vị
- feature flag · công tắc tính năng
- release · bản phát hành
- rollback · quay về bản cũ
- staged rollout · phát hành theo bậc
- incident · sự cố
- severity · mức nghiêm trọng
- analytics · đo hành vi người dùng
- secret · thông tin bí mật
- API · giao diện lập trình
- backward compatibility · tương thích ngược
- endpoint · điểm gọi
- migration · chuyển đổi dữ liệu
- schema · hình dạng dữ liệu
Chỗ đứng của bài này
Ba bài cùng nói về vùng kiểm soát chất lượng, không thay được nhau:
| Bài | Trả lời câu hỏi nào | Ai gác |
|---|---|---|
| Quality gate tự động | CI chặn được những gì, ở tầng nào | Máy |
| Chuẩn riêng cho Chat, Task và Bán hàng | Trong lúc viết code phải làm gì | Dev tự gác |
| Bài này | Xong hay chưa xong, và ai được quyền nói câu đó | Người ký tên |
Definition of Done là gate cuối do người gác. Thứ gì máy gác được thì đã nằm ở bài đầu tiên và không lặp lại ở đây.
Vì sao cần
"Xong" là từ dễ hiểu nhầm nhất trong một dự án. Dev nói xong nghĩa là code chạy trên máy mình. Tester nói xong nghĩa là đã thử hết case. PM nói xong nghĩa là người dùng đang dùng được. Ba cách hiểu này lệch nhau vài tuần công việc, và khoảng lệch chỉ lộ ra vào đúng tuần release.
Definition of Done xoá khoảng lệch đó bằng một danh sách chung, ai cũng kiểm tra được, không phụ thuộc vào việc ai đang gấp.
Phần CI đã chặn — đừng kiểm lại bằng tay
Nguyên tắc "máy kiểm tra được thì đừng bắt người kiểm tra" áp dụng trước tiên vào chính DoD. Những mục sau không nằm trong checklist của người, vì PR không merge được nếu chúng đỏ:
| Đã có gate tự động | Ngưỡng |
|---|---|
| Build trên mọi nền tảng đích | Đỏ là chặn |
| Type check, lint toàn dự án | Error hoặc warning mới là chặn |
| Unit test, integration test | Một test đỏ là chặn |
| Coverage trên code mới | Dưới 80% là chặn |
| Dependency scan, secret scan | Lỗ hổng mức cao trở lên là chặn |
| Kích thước gói cài đặt | Tăng quá 3% so với main là chặn |
| Migration không có kịch bản rollback | Là chặn |
Chi tiết ở Quality gate tự động. Nếu thấy mình đang kiểm tay một mục trong bảng trên, đó là dấu hiệu gate bị hỏng hoặc bị tắt — sửa gate, đừng bù bằng sức người.
DoD lõi — áp dụng cho mọi hạng mục
Tất cả các mục dưới đây là thứ CI không nhìn thấy được:
- Thoả đủ acceptance criteria đã viết, và người viết yêu cầu xác nhận, không phải dev tự xác nhận
- Đã qua code review và được approve
- Đã thử tay trên cả iOS và Android, gồm ít nhất một máy ở nhóm cấu hình thấp trong device matrix
- Các edge case đã thử: loading, empty state, mất mạng giữa chừng, server trả lỗi, và lần mở app đầu tiên khi chưa có dữ liệu
- Accessibility mức cơ bản: dynamic type ở cỡ lớn nhất không vỡ layout, screen reader đọc được các control chính — ngưỡng đầy đủ ở Chuẩn UI trên mobile
- Không ghi dữ liệu cá nhân hay nội dung người dùng ra log ở bất kỳ mức nào
- Analytics event của hạng mục đã gắn và đã thấy dữ liệu về ở môi trường test — xem Analytics event là một phần của yêu cầu
- Không vượt performance budget của màn hình bị ảnh hưởng
- Release note hoặc tài liệu đã cập nhật nếu hành vi thay đổi
DoD thêm, theo loại hạng mục
Một bug fix và một thay đổi schema không thể dùng chung một checklist. Phần cộng thêm:
| Loại hạng mục | Điều kiện cộng thêm |
|---|---|
| Feature mới | Có feature flag và flag đặt đúng trạng thái; có kế hoạch staged rollout; đã thống nhất chỉ số nào cho phép mở nấc tiếp |
| Bug fix | Có regression test tái hiện đúng bug, và test đó phải đỏ trên code cũ; đã trả lời được vì sao gate hiện tại không chặn được — xem shift left |
| Đổi schema hoặc dữ liệu trên máy | Đã test upgrade từ phiên bản đang chạy ngoài production, không chỉ cài mới; có kịch bản rollback; dữ liệu cũ không mất |
| Đổi API contract | Phiên bản app cũ vẫn gọi được — xem backward compatibility |
| Nâng thư viện | Đã đọc changelog phần breaking change; đã chạy luồng chính bằng tay, không chỉ dựa vào test xanh |
| Đổi config hoặc flag ngoài production | Ghi lại ai đổi, đổi gì, lúc nào; có đường về trạng thái cũ trong dưới 5 phút |
DoD thêm, theo module
Ba module có ba loại rủi ro khác nhau nên gate cũng khác nhau. Không chép lại luật ở đây — điều kiện là checklist trước PR của module đó đã tick đủ, theo Chuẩn riêng cho Chat, Task và Bán hàng:
| Module | Thứ dễ hỏng nhất | Điều kiện cứng thêm |
|---|---|---|
| Chat | Thứ tự, trùng tin, mất tin khi mạng chập chờn | Đã test airplane-mode round trip và gửi liên tiếp ở mạng chậm |
| Task | Phân quyền, trạng thái không nhất quán | Đã test gọi thẳng endpoint bằng tài khoản không có quyền |
| Bán hàng | Sai tiền, đơn trùng, mất audit trail | 2 approve, một người là chủ module Bán hàng; bảng test tính tiền có ca biên |
| Tầng dùng chung | Hỏng một chỗ là hỏng cả ba | 2 approve, một người là Chủ kỹ thuật |
Ai ký
Mỗi thứ có đúng một người chịu trách nhiệm. Với DoD, người đó không phải tác giả:
| Việc | Người xác nhận |
|---|---|
| Acceptance criteria đã thoả | Người viết yêu cầu |
| Code đủ chuẩn để merge | Người review |
| Rủi ro riêng của module đã được gác | Chủ module |
| Hạng mục được đóng | Chủ sản phẩm |
Vai trò định nghĩa ở Vai trò và trách nhiệm. Không dòng nào trong bảng được ký bằng câu "tôi thấy ổn rồi" — mỗi dòng phải trỏ tới một bằng chứng quan sát được.
"Xong" không phải là "đã merge"
Đây là chỗ quy mô 500.000 người dùng đổi luật. Merge xong, hạng mục mới chỉ hết phần rủi ro nhìn thấy trước được. Phần còn lại chỉ lộ ra trên dữ liệu thật.
Một hạng mục chỉ được đóng khi đã đi qua staged rollout và chỉ số ổn định ở nấc cuối:
merge ──→ 0,5% ──→ 2% ──→ 10% ──→ 50% ──→ 100% ──→ ĐÓNG
2.500 10.000 50.000 250.000 500.000
│ │ │ │
└────────┴───────┴────────┴──→ chỉ số xấu đi: tắt flag,
mở lại hạng mục, chưa đóng
Thang nấc và thời gian chờ lấy theo Release từng phần và feature flag — bài này không giữ bản sao.
Chỉ số cần nhìn ở mỗi nấc nằm ở Quy tắc cảnh báo. Lý do phải đọc tỷ lệ ra số người nằm ở Chất lượng ở quy mô 500.000 người dùng: 0,1% không phải số nhỏ, nó là 500 người thật đang gặp lỗi.
Ngoại lệ, và đường waiver
Có ngoại lệ. Nhưng ngoại lệ phải để lại dấu vết.
Incident P0 đang diễn ra được đi tắt để vá trước, theo quy trình xử lý sự cố. Phần DoD bị nợ ghi vào sổ nợ kỹ thuật và trả trong release kế tiếp.
Mọi trường hợp khác đi qua đường waiver trong Mẫu checklist trước release: bỏ điều kiện nào, vì sao, rủi ro là gì, ai chịu, bao giờ trả — có người ký tên.
Hai việc bị cấm, không ngoại lệ:
- Hạ severity của một bug để nó không chặn release. Đường đúng là waiver, không phải đổi nhãn.
- Sửa Definition of Done giữa kỳ cho vừa với thứ đang làm dở. Đổi DoD là quyết định của cả đội, bàn ở retro, không phải quyết định của người đang kẹt deadline.
Khi thiếu thời gian, cách xử lý đúng là cắt scope hạng mục cho nhỏ lại, giữ nguyên DoD. Chất lượng là ràng buộc, không phải thứ đem ra đánh đổi.
Khi một điều kiện liên tục bị bỏ qua
Đó là tín hiệu, không phải lỗi cá nhân. Ba khả năng, xử lý khác nhau:
| Hiện tượng | Nghĩa là | Việc cần làm |
|---|---|---|
| Ai cũng quên một mục | Mục đó viết mơ hồ, không kiểm được | Viết lại cho kiểm được, hoặc bỏ |
| Ai cũng làm nhưng rất tốn công | Thiếu công cụ | Tự động hoá, đẩy xuống CI |
| Chỉ vài hạng mục vi phạm | Hạng mục quá to | Chẻ nhỏ ở chặng làm rõ |
Im lặng bỏ qua là lựa chọn tệ nhất, vì nó biến DoD thành thứ trang trí và cả đội đều biết điều đó.
Giới hạn
- Checklist này giả định CI đã có đủ bốn tầng gate. Chưa có thì việc cần làm trước là dựng gate, không phải bắt người kiểm tay từng mục.
- Phần accessibility ở đây mới là mức cơ bản, đủ để không chặn người dùng. Chưa phải tuân thủ một tiêu chuẩn cụ thể nào.
- Rà lại danh sách mỗi quý ở retro. Điều kiện nào ba quý liền không bắt được lỗi nào thì bỏ — DoD dài không đồng nghĩa với DoD tốt.

