Mở đầu — vì sao bài này quan trọng
Trong hồ sơ ứng tuyển BA, có một thứ mà nhà tuyển dụng sẽ đọc rất kỹ, đôi khi còn kỹ hơn cả CV của bạn: cách bạn viết user story và acceptance criteria (AC). Đây là "sản phẩm đầu ra" hằng ngày của một BA. Một BA giỏi domain nhưng viết user story lủng củng thì dev đọc xong vẫn không biết phải build cái gì, QA không biết test cái gì, và sprint planning sẽ biến thành buổi tranh cãi kéo dài hai tiếng.
Tin vui cho bạn — người đến từ Customer Service — là: bạn có một lợi thế mà rất nhiều BA "chính quy" không có. Bạn đã dành hàng nghìn giờ nghe khách hàng nói chính xác họ muốn gì, họ đau ở đâu, và họ thất vọng thế nào khi sản phẩm không làm được điều đó. Cái "So that…" (để mà…) trong user story — phần mà đa số BA junior viết cho có lệ — chính là phần bạn cảm nhận rõ nhất. Bạn đã sống trong nỗi đau của người dùng mỗi ngày.
Bài này không dạy lại "user story là gì" theo kiểu sách giáo khoa. Chúng ta sẽ tập trung vào cách viết user story và AC theo phong cách của một ex-CS — tận dụng vốn liếng thấu cảm khách hàng và tư duy tình huống mà bạn đã tích lũy — để tạo ra những artifact vừa rõ ràng cho dev, vừa không bao giờ quên góc nhìn người dùng thật. Ở Bài 4 bạn đã học viết user story cơ bản từ góc nhìn CS; bài này đi sâu hơn vào style và acceptance criteria — hai thứ tạo nên sự khác biệt giữa BA nghiệp dư và BA được tin tưởng.
Khái niệm cốt lõi
User story chuẩn và ba thành phần
User story là một cách mô tả tính năng dưới góc nhìn của người dùng, ngắn gọn, dễ hiểu. Cấu trúc kinh điển gồm ba phần:
- As a [vai trò / loại người dùng] — Là một…
- I want to [hành động / tính năng] — Tôi muốn…
- So that [giá trị / lợi ích] — Để mà…
Điểm mấu chốt: user story không phải là bản đặc tả kỹ thuật. Nó là lời mời để cả team ngồi lại thảo luận. Ron Jeffries — một trong những người đặt nền móng Agile — gọi đây là mô hình 3C: Card (tấm thẻ ghi ngắn gọn), Conversation (cuộc trò chuyện làm rõ), Confirmation (điều kiện xác nhận là AC). Rất nhiều BA junior chỉ viết Card rồi bỏ quên hai chữ C còn lại. Ex-CS như bạn lại có bản năng tự nhiên cho phần Conversation — vì bạn quen đào sâu để hiểu vấn đề thật sự của khách hàng.
Lợi thế ex-CS trong việc viết user story
Đây là phần "linh hồn" của bài. Ex-CS có ba vũ khí riêng:
1. Bạn viết được phần "So that" thật, không phải "So that" giả. BA thường viết cho xong: "…để tôi có thể sử dụng tính năng này." Đó là "So that" vô nghĩa. Còn bạn — người đã nghe khách hàng gào lên trên điện thoại — viết được: "…để tôi không phải chờ 3 ngày mới biết đơn của mình đã bị hủy, tránh việc đặt lại và bị trừ tiền hai lần." Giá trị thật, đau thật.
2. Bạn nghĩ được nhiều persona (vai trò) hơn. Sản phẩm không chỉ có một loại người dùng. Có khách hàng mới, khách hàng VIP, khách hàng đang khiếu nại, và cả... nhân viên CS đứng sau xử lý. Ex-CS nhớ tất cả các nhóm này vì bạn đã phục vụ họ.
3. Bạn viết được edge case trong AC. Đây là điểm mạnh lớn nhất. Vì bạn từng xử lý ticket, bạn biết mọi thứ có thể hỏng ở đâu: khi khách nhập sai định dạng, khi mạng rớt giữa chừng, khi khách bấm nút hai lần. Những tình huống này chính là "gold" cho acceptance criteria.
Acceptance Criteria — nơi ex-CS toả sáng
Acceptance Criteria (AC) là tập hợp các điều kiện phải thỏa mãn để user story được coi là "hoàn thành". AC trả lời câu hỏi: "Làm sao ta biết cái này đã đúng?" Có hai cách viết AC phổ biến:
Cách 1 — Given/When/Then (Gherkin): Đây là format có cấu trúc nhất, dev và QA đều thích.
- Given [bối cảnh ban đầu] — Cho trước rằng…
- When [hành động xảy ra] — Khi…
- Then [kết quả mong đợi] — Thì…
Cách 2 — Checklist / Rule-based: Danh sách các điều kiện dạng gạch đầu dòng. Đơn giản, phù hợp với các story không có luồng phức tạp.
Nguyên tắc vàng của một AC tốt: nó phải testable (kiểm thử được) và binary (đúng/sai rõ ràng). "Trang tải nhanh" là AC tồi. "Trang tải trong dưới 2 giây với kết nối 4G" mới là AC tốt. Ex-CS quen với con số cụ thể (thời gian chờ, SLA) nên rất dễ viết loại AC định lượng này.
INVEST — thước đo chất lượng story
Một user story tốt nên đạt tiêu chí INVEST: Independent (độc lập), Negotiable (có thể thương lượng), Valuable (có giá trị), Estimable (ước lượng được), Small (đủ nhỏ), Testable (kiểm thử được). Bạn không cần thuộc lòng, nhưng khi viết xong một story, hãy tự hỏi: "Story này có mang lại giá trị rõ ràng không? Team có ước lượng được không? Nó có quá to không?"
Tình huống thực tế
Ví dụ 1 — Tiki: từ "So that" giả sang "So that" thật
Giả sử bạn vừa chuyển sang làm BA cho một sàn thương mại điện tử tương tự Tiki. Team đang làm tính năng "Hủy đơn hàng". Một BA khác trong nhóm viết:
> Là một khách hàng, tôi muốn hủy đơn hàng, để tôi có thể hủy đơn hàng.
Nhìn thì có vẻ đúng cấu trúc, nhưng phần "So that" rỗng tuếch. Bạn — từng ngồi ở tổng đài Tiki hai năm — biết rõ tại sao khách muốn hủy. Bạn viết lại thành ba story riêng biệt:
> Story A: Là một khách hàng vừa đặt nhầm số lượng, tôi muốn hủy đơn trong vòng 30 phút sau khi đặt, để tôi không bị giao 10 hộp thay vì 1 và mất công hoàn trả. > > Story B: Là một khách hàng thấy giá giảm sâu hơn ở nơi khác, tôi muốn hủy đơn chưa được đóng gói, để tôi mua được giá tốt hơn mà không mất tiền cọc. > > Story C: Là một nhân viên CS, tôi muốn hủy đơn thay cho khách khi khách gọi điện, để giải quyết cho những khách không rành thao tác trên app.
Bạn thấy điều gì không? Từ một story mờ nhạt, bạn đã tách ra ba nhu cầu thật với ba ngữ cảnh khác nhau, kèm cả persona nhân viên CS mà BA thường quên. AC cho Story A của bạn sẽ có ngay một edge case đắt giá:
> Given đơn hàng đã đặt được hơn 30 phút, When khách bấm "Hủy đơn", Then hệ thống hiển thị thông báo "Đơn đã vào xử lý, vui lòng liên hệ CSKH" thay vì nút hủy.
Bài học: Ex-CS biến "So that" mờ thành "So that" đau — và nhờ đó tách được story đúng theo nhu cầu thật, không phải theo trí tưởng tượng.
Ví dụ 2 — Ngân hàng số Timo: edge case cứu cả một sprint
Bạn làm BA cho một app ngân hàng số kiểu Timo. Team làm tính năng "Chuyển tiền nhanh 24/7". Bản story ban đầu rất mượt:
> Là một người dùng, tôi muốn chuyển tiền tới số tài khoản bất kỳ, để tôi thanh toán cho người khác nhanh chóng.
AC ban đầu chỉ có luồng thành công (happy path): nhập số tài khoản → nhập số tiền → xác thực OTP → chuyển thành công. Nhưng bạn từng làm CS mảng thanh toán, nên bạn nhớ những cuộc gọi kinh hoàng của khách. Bạn thêm vào AC:
> AC1 — Given khách nhập số tiền vượt hạn mức 100 triệu/ngày, When bấm "Chuyển", Then hệ thống chặn và hiển thị hạn mức còn lại trong ngày. > > AC2 — Given khách bấm "Chuyển" hai lần liên tiếp do app lag, When lệnh thứ hai được gửi trong vòng 10 giây, Then hệ thống chặn giao dịch trùng và thông báo "Giao dịch đang xử lý". > > AC3 — Given mất kết nối mạng ngay sau khi nhập OTP, When khách mở lại app, Then hệ thống hiển thị đúng trạng thái giao dịch (thành công / thất bại / đang xử lý), không để khách mù mờ.
AC2 — chống double-submit — chính là tình huống bạn từng xử lý hàng chục ticket "tôi bị trừ tiền hai lần". Trong buổi refinement, dev thừa nhận họ chưa nghĩ tới case này. Một AC của bạn có thể đã cứu team khỏi một sự cố production nghiêm trọng và hàng loạt ticket khiếu nại.
Bài học: Trong ngành ngân hàng, edge case không phải "nice to have" — nó là ranh giới giữa an toàn và thảm họa. Ex-CS nhìn thấy những case này bằng ký ức, không phải bằng lý thuyết.
Ví dụ 3 — Grab: viết AC định lượng từ tư duy SLA
Bạn làm BA cho một nền tảng gọi xe kiểu Grab, phụ trách tính năng "Hủy chuyến". Một BA junior viết AC: "Khi khách hủy chuyến, hệ thống phải xử lý nhanh và công bằng." Câu này nghe hay nhưng không thể test được — "nhanh" là bao nhiêu, "công bằng" nghĩa là gì?
Nhờ nền CS quen với SLA (cam kết mức dịch vụ) và các con số cụ thể, bạn viết lại:
> AC1 — Given khách hủy chuyến trong vòng 3 phút đầu sau khi tài xế nhận cuốc, Then không thu phí hủy. > > AC2 — Given khách hủy sau 3 phút HOẶC khi tài xế đã di chuyển hơn 300m, Then thu phí hủy 10.000đ và hiển thị rõ lý do trước khi khách xác nhận. > > AC3 — Given tài xế là người hủy, Then khách không bị thu bất kỳ khoản phí nào và được ưu tiên ghép chuyến mới trong 60 giây.
Mỗi điều kiện đều có con số, có ngưỡng, có kết quả rõ ràng — QA test được ngay, dev build được ngay, và quan trọng nhất: khách hàng không cảm thấy bị "móc túi" oan.
Bài học: Tư duy SLA của ex-CS chuyển thẳng thành AC định lượng. Ở đâu người khác viết "nhanh", "tốt", "hợp lý" thì bạn viết ra con số kiểm thử được.
Hướng dẫn từng bước
Đây là quy trình bạn có thể áp dụng ngay để viết một user story + AC hoàn chỉnh theo style ex-CS:
Bước 1 — Xác định persona thật, không phải "user" chung chung. Đừng viết "Là một người dùng". Hãy hỏi: người dùng này là ai, trong hoàn cảnh nào? Khách mới hay khách cũ? Đang vui hay đang bực? Tận dụng trí nhớ CS của bạn để liệt kê các nhóm khách thật.
Bước 2 — Đào phần "So that" đến tận gốc. Viết nháp lợi ích, rồi hỏi "để làm gì?" thêm 2 lần nữa (kỹ thuật 5 Whys mini). Dừng lại khi bạn chạm được nỗi đau hoặc giá trị thật mà khách quan tâm.
Bước 3 — Viết Card ngắn gọn theo cấu trúc As a / I want / So that. Giữ nó ngắn, một câu, dễ đọc trong 10 giây.
Bước 4 — Liệt kê happy path trong AC trước. Dùng Given/When/Then cho luồng thành công cơ bản nhất.
Bước 5 — Thêm edge case từ ký ức ticket của bạn. Đây là lúc tỏa sáng. Tự hỏi: Khách từng khiếu nại gì về loại tính năng này? Có thể hỏng ở đâu? Mỗi câu trả lời là một AC. Ưu tiên: nhập sai định dạng, vượt giới hạn, thao tác trùng, mất kết nối, quyền truy cập.
Bước 6 — Định lượng mọi tính từ. Rà lại AC, thay mọi từ "nhanh / nhiều / rõ ràng" bằng con số cụ thể.
Bước 7 — Kiểm tra bằng INVEST. Story có đủ nhỏ để làm trong một sprint không? Có testable không? Nếu quá to, tách ra.
Bước 8 — Đọc lại như một QA. Tự hỏi từng AC: "Tôi có thể viết ra một test case đúng/sai từ dòng này không?" Nếu không, viết lại.
Lỗi thường gặp & mẹo
Lỗi 1 — Viết user story như đặc tả kỹ thuật. Ví dụ sai: "Là một user, tôi muốn hệ thống gọi API POST /orders/cancel với status code 200." Đó là mô tả giải pháp, không phải nhu cầu. Story mô tả cái gì và tại sao, để phần làm thế nào cho dev quyết định.
Lỗi 2 — "So that" giả. Lặp lại phần "I want" ở phần "So that". Mẹo: nếu bỏ được chữ "So that" mà story không mất nghĩa, thì bạn đang viết "So that" rỗng.
Lỗi 3 — AC chỉ có happy path. Đây là lỗi giết chết sản phẩm. Mẹo ex-CS: với mỗi story, ép mình viết ít nhất 2 edge case dựa trên trải nghiệm ticket.
Lỗi 4 — Story quá to (epic đội lốt story). Nếu AC dài hơn 8-10 dòng, gần như chắc chắn bạn cần tách story. Mẹo: tách theo ngữ cảnh khách hàng (khách mới vs khách cũ) hoặc theo bước trong luồng.
Lỗi 5 — AC không đo được. Mọi tính từ mơ hồ đều là "nợ kỹ thuật của tài liệu". Mẹo: đọc lại và gạch chân mọi tính từ, rồi thay bằng con số.
Mẹo vàng cho ex-CS: Giữ một "sổ tay nỗi đau" (pain log) — ghi lại các loại khiếu nại phổ biến bạn từng gặp. Khi viết AC, mở sổ ra và đối chiếu. Đây là tài sản độc quyền mà BA thường không có.
Bài tập thực hành
Hãy chọn một tính năng quen thuộc — ví dụ "Đổi mật khẩu trên app ngân hàng" — và làm các việc sau:
- Viết 3 user story cho 3 persona khác nhau (ví dụ: khách quên mật khẩu, khách muốn đổi định kỳ vì lý do bảo mật, nhân viên CS hỗ trợ khách qua điện thoại). Mỗi story phải có phần "So that" thật, chạm được nỗi đau/giá trị.
- Viết AC theo Given/When/Then cho story "khách quên mật khẩu", gồm: 1 happy path + tối thiểu 3 edge case. Gợi ý các edge case đáng nghĩ: nhập sai OTP quá 3 lần, đường link reset hết hạn, khách dùng đúng mật khẩu cũ làm mật khẩu mới, tài khoản đang bị khóa tạm thời.
- Định lượng hóa: Rà lại toàn bộ AC và đảm bảo không còn tính từ mơ hồ nào — mỗi ngưỡng thời gian, số lần thử, độ dài mật khẩu đều phải có con số.
- Tự chấm điểm INVEST: Với mỗi story, đánh dấu xem có đạt Small và Testable không. Nếu một story có quá nhiều AC, hãy thử tách đôi.
Tóm tắt
- User story gồm ba phần As a / I want / So that, và giá trị thật nằm ở phần "So that" — nơi ex-CS có lợi thế vượt trội nhờ đã sống trong nỗi đau khách hàng.
- Acceptance Criteria trả lời câu hỏi "làm sao biết cái này đúng?". AC tốt phải testable và binary, ưu tiên viết theo Given/When/Then.
- Vũ khí riêng của ex-CS là edge case — những tình huống hỏng hóc mà bạn đã xử lý qua hàng nghìn ticket. Đây là thứ biến AC của bạn thành "gold" trong mắt dev và QA.
- Tư duy SLA và con số cụ thể từ nền CS giúp bạn viết AC định lượng, ở đâu người khác viết "nhanh, tốt" thì bạn viết ra ngưỡng đo được.
- Quy trình 8 bước: xác định persona thật → đào "So that" tận gốc → viết Card → happy path → thêm edge case từ ký ức ticket → định lượng → kiểm INVEST → đọc lại như QA.
- Đừng viết story như đặc tả kỹ thuật, đừng để "So that" giả, và tuyệt đối đừng chỉ viết happy path. Giữ một "sổ tay nỗi đau" làm tài sản độc quyền của riêng bạn.