Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là PM (Product Manager) của một đội phát triển tại một startup fintech ở TP.HCM. Bạn viết một user story: "Là khách hàng, tôi muốn đặt lại mật khẩu để đăng nhập lại được tài khoản." Nghe rất rõ ràng, đúng không? Nhưng ba ngày sau, dev bàn giao tính năng và bạn phát hiện: họ cho phép đặt mật khẩu chỉ 4 ký tự, không gửi email xác nhận, và link reset không hề hết hạn. Dev không sai — họ làm đúng những gì story yêu cầu. Vấn đề nằm ở chỗ story của bạn thiếu Acceptance Criteria — thiếu định nghĩa rõ ràng thế nào là "làm xong đúng".
Đây chính là khoảng cách chết người trong quản lý sản phẩm: khoảng cách giữa "điều PM nghĩ" và "điều dev hiểu". Trong toàn bộ khóa học này, chúng ta đã học cách cấu trúc công việc (Epic, Story, Task ở Bài 5), cách thiết kế workflow (Bài 7), cách viết story point (Bài 14). Nhưng tất cả những thứ đó sẽ vô nghĩa nếu bạn không trả lời được câu hỏi cốt lõi: "Khi nào thì một công việc được coi là HOÀN THÀNH?"
Bài 15 tập trung vào hai công cụ trả lời câu hỏi đó: Acceptance Criteria (AC) — tiêu chí chấp nhận cho từng story, và Definition of Done (DoD) — định nghĩa hoàn thành chung cho cả đội. Hai khái niệm này thường bị nhầm lẫn, và việc dùng sai chúng là một trong những nguyên nhân hàng đầu gây ra rework (làm lại), tranh cãi lúc nghiệm thu, và sprint bị "carry over" (đẩy sang sprint sau). Nắm vững chúng, bạn sẽ giảm mạnh mâu thuẫn giữa PM và dev, tăng chất lượng bàn giao, và quan trọng nhất: bảo vệ được uy tín của chính mình khi demo trước sếp.
Khái niệm cốt lõi
Acceptance Criteria (AC) — tiêu chí chấp nhận cho TỪNG story
Acceptance Criteria là tập hợp các điều kiện cụ thể mà một user story phải thỏa mãn để được coi là "chấp nhận được". Nói cách khác, AC là bản hợp đồng nhỏ giữa PM và dev cho riêng story đó: "Nếu tất cả những điều này đúng, tôi sẽ nghiệm thu."
Đặc điểm quan trọng của AC:
- Gắn với từng story cụ thể. Mỗi story có AC riêng, không dùng chung. Story "đặt lại mật khẩu" có AC khác hoàn toàn story "hiển thị lịch sử giao dịch".
- Mô tả HÀNH VI, không mô tả cách làm. AC nói "hệ thống phải làm gì", không nói "dev phải code thế nào". Bạn định nghĩa kết quả mong đợi, để dev tự do chọn giải pháp kỹ thuật.
- Có thể kiểm chứng được (testable). Mỗi tiêu chí phải trả lời được đúng/sai một cách khách quan. "Trang phải nhanh" là AC tồi. "Trang tải xong dưới 2 giây với kết nối 4G" là AC tốt.
- Do PM viết, tinh chỉnh cùng dev và QA. PM khởi tạo AC dựa trên hiểu biết về nhu cầu người dùng, sau đó refine (tinh chỉnh) trong buổi backlog refinement với đội. Dev có thể chỉ ra edge case (trường hợp biên) mà PM chưa nghĩ tới; QA chỉ ra điều kiện cần test.
Định dạng Given-When-Then (Gherkin)
Cách viết AC phổ biến và chuyên nghiệp nhất là dùng cú pháp Gherkin với ba từ khóa:
- Given (Cho trước / Bối cảnh): trạng thái ban đầu, điều kiện tiên quyết.
- When (Khi): hành động mà người dùng thực hiện.
- Then (Thì): kết quả mong đợi mà hệ thống trả về.
> Given người dùng đã đăng ký với email hợp lệ > When họ nhập email và bấm "Gửi link đặt lại mật khẩu" > Then hệ thống gửi một email chứa link đặt lại có hiệu lực trong 15 phút
Bạn có thể có nhiều kịch bản Given-When-Then cho một story, bao gồm cả kịch bản lỗi:
> Given người dùng nhập email chưa từng đăng ký > When họ bấm "Gửi link" > Then hệ thống hiển thị thông báo "Nếu email tồn tại, chúng tôi đã gửi link" (không tiết lộ email có tồn tại hay không, vì lý do bảo mật)
Định dạng Given-When-Then mạnh ở chỗ nó buộc bạn suy nghĩ có hệ thống về mọi luồng: luồng thành công (happy path), luồng lỗi, và các trường hợp biên. Ngoài Gherkin, một số đội dùng dạng checklist đơn giản (danh sách các điều kiện gạch đầu dòng). Checklist nhanh hơn nhưng dễ bỏ sót bối cảnh; Given-When-Then chậm hơn nhưng đầy đủ hơn. Với các tính năng phức tạp, mình khuyên dùng Gherkin.
Definition of Done (DoD) — định nghĩa hoàn thành CHUNG
Nếu AC là hợp đồng riêng cho từng story, thì Definition of Done là bộ tiêu chuẩn chất lượng chung áp dụng cho MỌI story của đội. DoD trả lời câu hỏi: "Bất kể story là gì, đội chúng ta coi như chưa xong nếu chưa làm những việc này."
Một DoD điển hình của một đội phát triển phần mềm có thể gồm:
- Code đã được review bởi ít nhất một dev khác (peer review).
- Đã viết unit test và tất cả test pass.
- Đã merge vào nhánh chính, không làm hỏng build.
- Đã deploy lên môi trường staging và QA đã test.
- Tài liệu kỹ thuật / API đã được cập nhật.
- Không còn bug nghiêm trọng (critical/blocker) tồn đọng.
Phân biệt AC và DoD — đừng nhầm
Đây là điểm học viên hay nhầm nhất, nên mình muốn nhấn mạnh bằng một bảng so sánh tư duy:
| Acceptance Criteria | Definition of Done | |
|---|---|---|
| Phạm vi | Từng story riêng | Mọi story của đội |
| Nội dung | Hành vi/chức năng cụ thể | Tiêu chuẩn chất lượng quy trình |
| Ai viết | PM (refine cùng đội) | Cả đội thống nhất |
| Thay đổi | Mỗi story mỗi khác | Cố định, ít thay đổi |
| Ví dụ | "Link reset hết hạn sau 15 phút" | "Đã có unit test và code review" |
AC/DoD trong Jira — nơi lưu trữ thực tế
Trong Jira, AC thường được đặt trực tiếp trong phần Description của story, hoặc trong một custom field riêng tên "Acceptance Criteria" (chúng ta sẽ học cách tạo custom field ở Bài 18). Nhiều đội dùng checkbox trong description để dev tick từng tiêu chí khi hoàn thành.
DoD thì thường không đặt trong từng issue, mà được ghi ở một trang Confluence chung (Bài 22) rồi gắn link vào cột "Done" của board, hoặc đưa vào phần mô tả của workflow status "Done". Một số đội tạo một sub-task template cho các bước DoD lặp lại. Nguyên tắc: DoD phải luôn hiển thị, dễ tra cứu, để không ai "quên" nó.
Tình huống thực tế
Tình huống 1 — Startup giao hàng ở Hà Nội và cái story mơ hồ
Một startup logistics tại Hà Nội (giả định tên GiaoNhanh) đang xây tính năng "theo dõi đơn hàng thời gian thực". PM viết story: "Là người nhận, tôi muốn xem đơn hàng đang ở đâu."
Sprint đầu, dev làm ra một trang hiển thị trạng thái đơn dạng chữ: "Đang giao". PM demo cho CEO và bị hỏi ngay: "Thế cái bản đồ đâu? Đối thủ có bản đồ real-time mà." PM ngớ người vì trong đầu chị luôn nghĩ có bản đồ, nhưng chưa từng viết ra. Kết quả: story bị làm lại, mất thêm một sprint, và niềm tin của CEO vào đội bị lung lay.
Sprint sau, PM viết lại AC theo Gherkin:
> Given đơn hàng đang ở trạng thái "Đang giao" > When người nhận mở màn hình theo dõi > Then hiển thị vị trí shipper trên bản đồ, cập nhật tối đa mỗi 30 giây, kèm thời gian dự kiến đến (ETA)
Bài học: Story chỉ là tiêu đề ngắn để nhớ; AC mới là nội dung thực sự. Cái gì không viết ra trong AC thì dev không có nghĩa vụ làm, và bạn không có quyền trách họ. Con số cụ thể (30 giây, ETA) biến kỳ vọng mơ hồ thành cam kết đo được.
Tình huống 2 — Ngân hàng số và Definition of Done cứu một phen suýt sập
Một đội phát triển tại một ngân hàng số ở Singapore đang chịu áp lực release tính năng chuyển khoản liên ngân hàng. Dev báo "code xong rồi, chạy được trên máy em". PM vì gấp deadline nên định cho lên production luôn.
May thay, đội này có DoD rõ ràng, trong đó có mục: "Đã chạy qua bộ regression test tự động và test bảo mật (security scan)." Khi ép story qua checklist DoD, họ phát hiện security scan báo lỗi: API chuyển khoản không kiểm tra giới hạn số lần thử trong ngày, tạo lỗ hổng cho tấn công dò tài khoản. Nếu release, thiệt hại tài chính và pháp lý có thể rất lớn.
Nhờ DoD chặn lại, story bị giữ thêm hai ngày để vá lỗ hổng, rồi mới release an toàn.
Bài học: DoD là "phanh an toàn" của đội, đặc biệt trong các lĩnh vực rủi ro cao như tài chính, y tế. Nó bảo vệ đội khỏi chính áp lực deadline của mình. Một AC tốt đảm bảo tính năng đúng; một DoD tốt đảm bảo tính năng đủ chất lượng để giao. Hai thứ này bổ sung cho nhau, không thay thế nhau.
Tình huống 3 — Đội e-commerce và checklist DoD chống "80% done"
Một công ty thương mại điện tử tại TP.HCM (giả định tên ChợViệt) liên tục gặp cảnh sprint nào cũng có 2–3 story bị carry over sang sprint sau. Khi phân tích, PM phát hiện: dev hay báo "xong" khi code chạy được, nhưng thực ra chưa viết test, chưa cập nhật tài liệu, chưa để QA kiểm. Đến cuối sprint, những phần "còn thiếu" đó dồn lại thành đống việc không kịp làm.
PM và đội ngồi lại xây một DoD 6 mục, in ra dán ngay cạnh board Kanban và thêm vào Jira dưới dạng checklist sub-task. Quy tắc mới: story không được kéo sang cột "Done" nếu chưa tick đủ 6 mục. Sau 3 sprint, tỷ lệ carry over giảm từ khoảng 30% xuống dưới 10%, và số bug phát hiện sau release giảm gần một nửa vì QA luôn được test trước khi đóng story.
Bài học: DoD chỉ có giá trị khi nó được thực thi chứ không phải treo cho đẹp. Gắn DoD vào workflow board (không cho chuyển sang Done nếu chưa đủ) biến nó từ khẩu hiệu thành cơ chế kiểm soát chất lượng thật sự.
Hướng dẫn từng bước
Đây là quy trình mình khuyên bạn áp dụng để xây AC và DoD một cách bài bản.
Bước 1 — Với mỗi story, xác định "happy path" trước. Hỏi: người dùng làm đúng thì kết quả mong đợi là gì? Viết kịch bản Given-When-Then đầu tiên cho luồng thành công.
Bước 2 — Liệt kê các luồng lỗi và edge case. Người dùng nhập sai thì sao? Mất mạng giữa chừng thì sao? Dữ liệu rỗng thì sao? Mỗi tình huống là một kịch bản Given-When-Then bổ sung. Đây là nơi tách biệt PM giỏi và PM thường: PM giỏi nghĩ được nhiều edge case.
Bước 3 — Kiểm tra tính testable. Đọc lại từng AC và tự hỏi: "QA có thể trả lời đúng/sai một cách khách quan không?" Nếu có từ mơ hồ như "nhanh", "đẹp", "dễ dùng" — hãy lượng hóa bằng con số hoặc điều kiện cụ thể.
Bước 4 — Refine cùng đội trong buổi backlog refinement. Đọc AC cho dev và QA nghe. Hỏi: "Có edge case nào tôi bỏ sót không? Có gì bất khả thi về mặt kỹ thuật không?" Cập nhật AC theo phản hồi. AC là sản phẩm của cả đội, không phải bản độc thoại của PM.
Bước 5 — Xây DoD một lần cho cả đội (không phải cho từng story). Tổ chức một buổi workshop, hỏi cả đội: "Với chúng ta, thế nào là một story thực sự hoàn thành?" Ghi lại 5–8 mục cốt lõi. Đừng tham lam nhét quá nhiều mục khiến DoD trở nên bất khả thi.
Bước 6 — Gắn AC và DoD vào Jira. Đặt AC trong description hoặc custom field của story. Đặt DoD ở nơi ai cũng thấy: Confluence, mô tả cột Done, hoặc sub-task checklist. Đảm bảo quy tắc "chưa đủ thì chưa Done" được cả đội tôn trọng.
Bước 7 — Rà soát định kỳ. Trong retrospective (Bài 13), hỏi: "DoD của chúng ta còn phù hợp không? AC gần đây có bị bỏ sót gì lặp lại không?" Cả AC và DoD đều là tài liệu sống, cần tiến hóa theo đội.
Lỗi thường gặp & mẹo
Lỗi 1 — Viết AC mô tả cách làm thay vì kết quả. Ví dụ: "Dùng Redis để cache danh sách sản phẩm." Đó là quyết định kỹ thuật, không phải AC. AC đúng phải là: "Danh sách sản phẩm tải xong dưới 1 giây khi có tối đa 500 sản phẩm." Để dev tự chọn Redis hay gì khác.
Lỗi 2 — Nhồi DoD vào AC hoặc ngược lại. Đừng viết "đã có unit test" vào AC của một story cụ thể — đó là việc của DoD, áp dụng cho mọi story. Ngược lại, đừng đưa hành vi chức năng riêng của một tính năng vào DoD chung.
Lỗi 3 — AC quá mơ hồ, không testable. "Giao diện phải thân thiện" là AC vô dụng. Hãy hỏi "thân thiện nghĩa là gì, đo bằng cách nào?" rồi viết điều kiện cụ thể.
Lỗi 4 — DoD chỉ nằm trên giấy. Nhiều đội có DoD đẹp nhưng không ai kiểm khi đóng story. Mẹo: cấu hình Jira/board sao cho không thể kéo story sang Done nếu chưa tick checklist DoD.
Lỗi 5 — PM viết AC một mình, không refine với đội. Kết quả là bỏ sót edge case kỹ thuật hoặc yêu cầu bất khả thi. Luôn đọc AC to lên trong buổi refinement.
Mẹo vàng: Một AC tốt trả lời câu "tính năng này làm ĐÚNG chưa?"; một DoD tốt trả lời câu "tính năng này giao ĐƯỢC chưa?". Ghi nhớ hai câu hỏi này, bạn sẽ không bao giờ nhầm lẫn hai khái niệm.
Bài tập thực hành
- Viết AC cho một story quen thuộc. Chọn tính năng "đăng nhập bằng số điện thoại và mã OTP". Viết ít nhất 3 kịch bản Given-When-Then: một happy path (OTP đúng), một luồng lỗi (OTP sai), và một edge case (OTP hết hạn). Đảm bảo mỗi tiêu chí đều testable với con số cụ thể (ví dụ: OTP hết hạn sau bao nhiêu phút?).
- Soi lỗi AC. Cho AC sau: "Người dùng có thể tìm kiếm sản phẩm nhanh và chính xác." Hãy chỉ ra tại sao AC này tồi, và viết lại thành 2 tiêu chí testable.
- Xây DoD cho đội của bạn. Giả sử bạn là PM của một đội 5 người làm app di động. Viết một Definition of Done gồm 6 mục. Với mỗi mục, giải thích một câu tại sao nó cần thiết. Sau đó tự hỏi: mục nào sẽ khó thực thi nhất và bạn sẽ gắn nó vào Jira như thế nào?
- Phân loại. Cho danh sách sau, đánh dấu mục nào thuộc AC và mục nào thuộc DoD: (a) "Nút thanh toán chuyển sang trang cổng VNPay"; (b) "Code đã được review"; (c) "Giỏ hàng hiển thị đúng tổng tiền có VAT"; (d) "Đã deploy lên staging"; (e) "Không còn bug blocker".
Tóm tắt
- Acceptance Criteria (AC) là tiêu chí chấp nhận cho từng story, mô tả hành vi cụ thể, do PM viết và refine cùng đội, phải testable. Cách viết chuẩn là Given-When-Then (Gherkin), phủ cả happy path, luồng lỗi và edge case.
- Definition of Done (DoD) là tiêu chuẩn chất lượng chung cho mọi story, do cả đội thống nhất, cố định và ít thay đổi. Nó chống lại hội chứng "80% done" và bảo vệ đội khỏi áp lực deadline.
- Đừng nhầm hai khái niệm: AC trả lời "làm đúng chưa?"; DoD trả lời "giao được chưa?". Một story chỉ thực sự Done khi thỏa mãn cả hai.
- Thực thi mới quan trọng: gắn AC vào description/custom field của story, gắn DoD vào board/Confluence và cấu hình để không cho đóng story nếu chưa đủ. Rà soát cả hai định kỳ trong retrospective.