Functional Requirement(FR)
Mô tả hành vi hệ thống phải thực hiện: nhận đầu vào gì, xử lý ra sao, trả kết quả nào. Đọc xong một FR tốt là QC nghĩ ra được test case ngay mà không cần hỏi lại.
Định nghĩa
Trong mọi tài liệu, FR là phần dev đọc nhiều nhất. Cũng là phần bị cãi nhau nhiều nhất. Nó trả lời câu "hệ thống làm gì" ở mức hành vi quan sát được: cho đầu vào này thì hệ thống phản ứng thế nào, ghi gì, gửi gì, chặn gì.
Cách nhớ đơn giản: nếu bỏ yêu cầu đó đi mà hệ thống vẫn chạy nhưng thiếu một việc người dùng cần làm, đó là FR. Nếu bỏ đi mà hệ thống vẫn làm đủ việc, chỉ chậm hơn hoặc kém an toàn hơn, đó là NFR.
Một FR viết tốt là FR mà QC đọc xong viết được test case ngay, chứ không dừng ở chỗ khách đọc xong gật đầu.
Cách viết một FR
Công thức dùng được cho hầu hết trường hợp: [Điều kiện] + hệ thống + [động từ hành động] + [đối tượng] + [kết quả].
- "Khi số dư tài khoản nhỏ hơn số tiền giao dịch, hệ thống từ chối lệnh và hiển thị mã lỗi INSUFFICIENT_BALANCE."
- "Hệ thống gửi thông báo đẩy cho người nhận trong vòng 5 giây kể từ khi giao dịch chuyển tiền thành công."
Vài quy tắc nhỏ nhưng cứu được nhiều buổi họp:
- Một câu một ý. Thấy chữ "và" nối hai hành vi thì tách ra.
- Dùng "phải" cho bắt buộc, tránh "nên", "có thể" — dev sẽ hiểu là tuỳ chọn, và họ hiểu đúng.
- Viết cả luồng thất bại. Đa số FR chỉ mô tả happy path, và đa số bug ở UAT nằm ở nhánh còn lại.
- Ghi rõ ai được làm. "Người dùng huỷ đơn" và "quản trị viên huỷ đơn" là hai FR khác nhau về quyền.
- Gắn số hiệu (FR-ORD-012) để ma trận truy vết và test case bám vào được.
Ví dụ thực tế
Bốn giờ chiều, bộ phận chăm sóc khách hàng của một app ngân hàng số đẩy sang cho BA một khiếu nại: tiền điện đã trừ trong tài khoản mà bên điện lực vẫn báo nợ. Tính năng thu hộ hoá đơn điện đó chạy khoảng 26 nghìn lượt mỗi ngày.
- FR-BILL-01: Người dùng tra cứu hoá đơn điện bằng mã khách hàng 13 ký tự do nhà cung cấp cấp.
- FR-BILL-02: Nếu mã khách hàng không tồn tại ở phía nhà cung cấp, hệ thống hiển thị thông báo "Không tìm thấy hoá đơn" và không tạo bản ghi giao dịch.
- FR-BILL-03: Hệ thống chỉ cho thanh toán khi hoá đơn ở trạng thái chưa thanh toán do nhà cung cấp trả về trong 60 giây gần nhất.
- FR-BILL-04: Sau khi trừ tiền thành công, hệ thống gửi yêu cầu gạch nợ sang nhà cung cấp; nếu gạch nợ thất bại sau 3 lần thử, hệ thống tự động hoàn tiền về tài khoản nguồn trong vòng 15 phút và ghi log đối soát.
Ba câu đầu ai viết cũng ra. Câu thứ tư chỉ đến từ việc từng ngồi trả lời cái khiếu nại lúc bốn giờ chiều kia — và trả lời khi không có log đối soát nào để mở.
So sánh FR và NFR
| Functional Requirement | Non-Functional Requirement | |
|---|---|---|
| Trả lời | Hệ thống làm gì | Làm tốt đến mức nào |
| Ví dụ | Xuất báo cáo doanh thu theo ngày | Báo cáo 1 triệu dòng xuất xong dưới 30 giây |
| Cách kiểm | Test case chức năng, UAT | Test hiệu năng, pentest, kiểm tra cấu hình |
| Thiếu thì sao | Người dùng không làm được việc | Làm được nhưng chậm, kém an toàn, hay lỗi |
| Ai quan tâm nhất | Người dùng nghiệp vụ, PO | Kiến trúc sư, DevOps, bảo mật, vận hành |
| Hay bị bỏ quên | Ít | Rất nhiều, đặc biệt ở dự án nhỏ |
Lỗi hay gặp
Nhét business rule vào giữa FR. "Hệ thống áp dụng chiết khấu 5% cho khách VIP" — con số 5% và định nghĩa VIP là chính sách kinh doanh, tháng sau đổi thành 7% là chuyện thường. Viết FR là "hệ thống áp dụng tỷ lệ chiết khấu theo hạng khách hàng được cấu hình trong danh mục", rồi để con số ở phần business rule. Đổi chính sách thì chỉ sửa một chỗ.
Kiểu hỏng thứ hai là FR đi mô tả giao diện. "Nút Thanh toán được bật khi đủ điều kiện" — đủ điều kiện là gì, và mai đổi sang màn hình khác thì câu này còn đúng không.
Còn cái làm mình mất nhiều thời gian nhất khi đi làm: FR không nói gì về dữ liệu biên. Số tiền tối đa một giao dịch là bao nhiêu, nhập 0 thì sao, nhập số âm thì sao. Không viết thì dev tự quyết, và mỗi dev quyết một kiểu.
