Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là BA của một dự án xây dựng app đặt vé xem phim cho CGV. Bạn ngồi họp với khách hàng, ghi chú đầy ba trang giấy: "khách hàng muốn chọn ghế", "phải thanh toán bằng Momo", "có gửi vé qua email"... Rồi bạn đưa đống ghi chú đó cho team dev. Một tuần sau, dev hỏi: "Nếu khách chọn ghế rồi nhưng người khác đặt mất thì sao? Khách đăng nhập hay không cần đăng nhập? Thanh toán thất bại thì ghế có bị giữ không?". Bạn ngớ người, vì những câu hỏi đó không có trong ghi chú.
Đây chính là vấn đề mà Use Case Modeling sinh ra để giải quyết. Use Case không phải là một danh sách yêu cầu rời rạc, mà là một câu chuyện có đầu có cuối: ai làm gì, để đạt được điều gì, và chuyện gì xảy ra khi mọi thứ không suôn sẻ. Đối với một BA, đây là một trong những công cụ mạnh nhất để biến những mong muốn mơ hồ của stakeholder thành thứ mà developer và tester có thể hành động ngay.
Trong bài này, chúng ta sẽ đi sâu vào Use Case và một phần của UML (Unified Modeling Language) — ngôn ngữ mô hình hóa chuẩn quốc tế. Bạn sẽ học cách viết một use case đầy đủ, vẽ use case diagram, và quan trọng nhất: tư duy như một người kể chuyện hệ thống. Đây là kỹ năng nền tảng cho mọi dự án phần mềm bạn sẽ tham gia.
Khái niệm cốt lõi
Use Case là gì?
Use Case (tình huống sử dụng) mô tả một chuỗi tương tác giữa actor và hệ thống nhằm đạt được một mục tiêu cụ thể, có giá trị cho actor đó. Hãy nhớ ba từ khóa: tương tác, actor, mục tiêu.
Điều quan trọng nhất: một use case luôn đứng từ góc nhìn của actor và luôn hướng tới một mục tiêu hoàn chỉnh. "Đăng nhập" không phải là một use case tốt nếu nó đứng một mình, vì đăng nhập không phải là mục tiêu — không ai mở app chỉ để đăng nhập rồi thoát. "Đặt vé xem phim" mới là use case thực sự, vì nó mang lại giá trị: khách hàng có vé trong tay.
Actor là gì?
Actor là bất kỳ ai hoặc bất kỳ thứ gì tương tác với hệ thống nhưng nằm bên ngoài phạm vi hệ thống. Actor có thể là:
- Con người: Khách hàng, Nhân viên thu ngân, Quản trị viên (Admin).
- Hệ thống khác: Cổng thanh toán VNPay, hệ thống gửi SMS Brandname, API của ngân hàng.
- Thời gian: Ví dụ một tác vụ tự động chạy lúc 0h hằng ngày (time-triggered).
Use Case Diagram và các quan hệ
Use Case Diagram là sơ đồ trực quan trong UML, cho thấy bức tranh tổng thể: có những actor nào, họ thực hiện những use case nào, và ranh giới hệ thống (system boundary) nằm ở đâu. Trên sơ đồ:
- Actor được vẽ bằng hình người que (stick figure).
- Use case được vẽ bằng hình bầu dục (oval).
- Đường thẳng nối actor với use case gọi là association.
- Một hình chữ nhật bao quanh các use case thể hiện ranh giới hệ thống.
Include (bao gồm): Use case A luôn luôn gọi use case B như một phần bắt buộc. Ví dụ "Đặt vé" luôn include "Xác thực thanh toán". Mũi tên đứt nét, ghi <<include>>, trỏ từ A sang B. Dùng include để tránh lặp lại logic chung dùng ở nhiều nơi.
Extend (mở rộng): Use case B có thể mở rộng use case A trong một số điều kiện nhất định, nhưng không bắt buộc. Ví dụ "Đặt vé" có thể được extend bởi "Áp dụng mã giảm giá" — chỉ khi khách có mã. Mũi tên đứt nét, ghi <<extend>>, trỏ từ B sang A. Đây là điểm dễ nhầm: hướng mũi tên của extend ngược với include.
Generalization (tổng quát hóa): Một actor hoặc use case là trường hợp đặc biệt của cái khác. Ví dụ "Khách VIP" là một dạng tổng quát hóa của "Khách hàng", kế thừa mọi use case của Khách hàng và thêm phần riêng.
Use Case Template — trái tim của bài này
Use Case Diagram chỉ cho bạn bức tranh tổng quan. Nhưng giá trị thực sự nằm ở Use Case Specification — bản mô tả chi tiết dạng văn bản. Đây là một template chuẩn mà bạn nên thuộc lòng:
Use Case ID: UC-001
Use Case Name: Đặt vé xem phim
Actor chính: Khách hàng đã đăng nhập
Mô tả ngắn: Khách hàng chọn phim, suất chiếu, ghế và thanh toán để nhận vé điện tử.
Preconditions (Điều kiện tiên quyết):
- Khách hàng đã đăng nhập.
- Suất chiếu còn ghế trống.
Postconditions (Điều kiện kết thúc):
- Thành công: Vé được tạo, ghế bị khóa, email vé được gửi.
- Thất bại: Không có vé nào được tạo, ghế được trả lại.
Trigger (Khởi phát): Khách hàng bấm nút "Đặt vé" trên màn hình suất chiếu.Main Flow (Luồng chính / Happy path):
1. Khách hàng chọn suất chiếu.
2. Hệ thống hiển thị sơ đồ ghế còn trống.
3. Khách hàng chọn ghế.
4. Hệ thống tạm khóa ghế trong 10 phút.
5. Khách hàng chọn phương thức thanh toán và xác nhận.
6. Hệ thống gọi cổng thanh toán (include UC-Thanh toán).
7. Hệ thống tạo vé và gửi email.
8. Hệ thống hiển thị vé điện tử có mã QR.
Alternative Flows (Luồng thay thế):
4a. Ghế vừa bị người khác đặt: Hệ thống báo "Ghế đã có người chọn",
quay lại bước 2.
Exception Flows (Luồng ngoại lệ):
6a. Thanh toán thất bại: Hệ thống mở khóa ghế, báo lỗi,
cho phép thử lại tối đa 3 lần.
4b. Hết 10 phút giữ ghế: Hệ thống tự mở khóa ghế, thông báo hết giờ.
Business Rules:
- BR-01: Một khách chỉ giữ tối đa 8 ghế / 1 lần đặt.
- BR-02: Ghế giữ quá 10 phút sẽ tự động mở.
Cái khiến template này quý giá không phải Main Flow — ai cũng nghĩ ra được happy path. Giá trị nằm ở Alternative Flow và Exception Flow: chính những trường hợp "nếu... thì sao" mà ở đầu bài làm bạn ngớ người. Một BA giỏi được phân biệt với BA trung bình ở chỗ họ liệt kê được bao nhiêu nhánh lỗi này.
Tình huống thực tế
Ví dụ 1: Tiki và bài toán "Đặt hàng" tưởng đơn giản
Một nhóm BA tại một sàn TMĐT (giả định theo mô hình Tiki) nhận yêu cầu: "Làm chức năng đặt hàng". Trưởng nhóm viết một use case "Đặt hàng" và ban đầu chỉ có Main Flow 6 bước đơn giản: chọn hàng → vào giỏ → nhập địa chỉ → chọn thanh toán → xác nhận → nhận đơn.
Khi BA ngồi xuống viết Alternative và Exception Flow, mọi thứ bùng nổ. Họ phát hiện ra hơn 15 nhánh: sản phẩm hết hàng trong lúc đang đặt, mã giảm giá hết hạn, địa chỉ giao hàng ngoài vùng phục vụ, thanh toán bằng thẻ bị từ chối, khách hủy giữa chừng, tồn kho âm do hai người mua cùng lúc... Mỗi nhánh là một quyết định nghiệp vụ mà nếu không hỏi rõ stakeholder, dev sẽ tự đoán — và đoán sai.
Bài học rút ra: Use case ép bạn nghĩ tới biên (edge case) trước khi code. Con số 6 bước Main Flow nở ra thành 21 nhánh đã giúp team ước lượng đúng khối lượng công việc, thay vì estimate 2 tuần rồi vỡ kế hoạch thành 6 tuần.
Ví dụ 2: App giao đồ ăn và actor "ẩn"
Một startup giao đồ ăn ở TP.HCM (giả định, kiểu ShopeeFood) thuê BA mô hình hóa luồng "Giao đơn hàng". BA mới vào nghề chỉ vẽ hai actor: Khách hàng và Tài xế. Sếp review và hỏi: "Nhà hàng đâu? Hệ thống định vị GPS đâu? Cổng thanh toán đâu?".
Hóa ra use case "Giao đơn" có tới 5 actor: Khách hàng (primary), Nhà hàng (supporting — xác nhận có món), Tài xế (supporting), Hệ thống bản đồ Google Maps (supporting — tính quãng đường, ETA), và Cổng thanh toán (supporting). Thiếu bất kỳ actor nào, use case diagram sẽ che giấu một điểm tích hợp (integration point) mà sau này dev mới phát hiện và phải làm thêm.
Bài học rút ra: Luôn tự hỏi "hệ thống cần gọi tới ai để hoàn thành mục tiêu?". Mỗi câu trả lời thường là một supporting actor, và mỗi supporting actor thường là một API tích hợp cần lên kế hoạch sớm.
Ví dụ 3: Ngân hàng VN và sức mạnh của quan hệ Include
Một BA tại một ngân hàng số ở Việt Nam mô hình hóa app mobile banking. Cô nhận thấy nhiều use case — "Chuyển khoản", "Thanh toán hóa đơn", "Nạp tiền điện thoại" — đều có chung một bước: xác thực bằng OTP/Soft Token. Thay vì copy-paste bước xác thực vào từng use case (và mỗi lần quy định bảo mật thay đổi lại phải sửa ở 8 chỗ), cô tách riêng một use case "Xác thực giao dịch" và dùng quan hệ <<include>> từ tất cả use case giao dịch tới nó.
Khi Ngân hàng Nhà nước ra quy định mới về xác thực sinh trắc học cho giao dịch trên 10 triệu đồng, cô chỉ cần sửa một use case "Xác thực giao dịch". Toàn bộ các use case khác tự động kế thừa.
Bài học rút ra: Include không phải là trang trí sơ đồ — nó là công cụ tổ chức giúp tài liệu của bạn dễ bảo trì. Logic chung tách ra một chỗ thì khi thay đổi chỉ sửa một nơi.
Hướng dẫn từng bước
Đây là quy trình thực chiến để xây dựng use case model cho một tính năng:
Bước 1 — Xác định ranh giới hệ thống. Hỏi rõ: hệ thống ta đang xây là gì, cái gì nằm trong, cái gì nằm ngoài? Mọi thứ nằm ngoài và có tương tác đều là ứng viên actor.
Bước 2 — Liệt kê actor. Quét hai nhóm: ai dùng hệ thống (con người) và hệ thống cần gọi tới ai (hệ thống ngoài). Phân loại primary và supporting.
Bước 3 — Liệt kê các goal (mục tiêu) của từng actor. Với mỗi primary actor, hỏi: "Họ muốn đạt được gì khi dùng hệ thống?". Mỗi goal hoàn chỉnh là một use case. Đặt tên use case theo công thức động từ + danh từ, từ góc nhìn actor: "Đặt vé", "Hủy đơn", "Tra cứu lịch sử".
Bước 4 — Vẽ Use Case Diagram. Đặt actor hai bên, use case ở giữa trong khung ranh giới hệ thống, nối association. Thêm include/extend/generalization nếu cần. Giữ sơ đồ ở mức tổng quan — đừng nhồi quá 15-20 use case vào một sơ đồ.
Bước 5 — Viết Use Case Specification cho từng use case quan trọng. Theo template ở trên. Bắt đầu với Main Flow, rồi dành phần lớn thời gian cho Alternative và Exception Flow.
Bước 6 — Rà soát Business Rules. Mỗi khi trong flow xuất hiện một con số, một giới hạn, một điều kiện ("tối đa 8 ghế", "giữ 10 phút"), tách nó ra thành Business Rule có mã riêng để dễ tham chiếu và quản lý thay đổi.
Bước 7 — Review với stakeholder. Đọc use case như kể chuyện cho người nghiệp vụ nghe. Use case dạng văn bản có lợi thế lớn: người không biết kỹ thuật vẫn đọc hiểu và phản hồi được.
Lỗi thường gặp & mẹo
Lỗi 1 — Use case quá nhỏ, mô tả thao tác chứ không phải mục tiêu. "Bấm nút", "Nhập email", "Click submit" không phải use case. Đó là bước bên trong một use case. Mẹo: nếu cái tên không trả lời được câu "actor đạt được giá trị gì?", nó quá nhỏ.
Lỗi 2 — Use case quá lớn, gộp cả hệ thống vào một oval. "Quản lý cửa hàng" là một mớ hỗn độn, không phải use case. Mẹo: một use case nên hoàn thành trong một phiên làm việc của một actor.
Lỗi 3 — Nhầm include và extend. Nhớ mẹo: include là bắt buộc và luôn xảy ra (mũi tên trỏ tới cái được gọi), extend là tùy chọn và có điều kiện (mũi tên trỏ tới cái được mở rộng). Nếu bạn không chắc, hãy hỏi: "Cái này có luôn luôn xảy ra không?". Có → include. Đôi khi → extend.
Lỗi 4 — Bỏ qua exception flow. Đây là lỗi chí mạng và phổ biến nhất. Happy path chỉ là 20% công việc thực tế của dev; 80% còn lại là xử lý lỗi. Mẹo: với mỗi bước trong Main Flow, tự hỏi "bước này có thể fail thế nào?".
Lỗi 5 — Vẽ diagram quá chi tiết. Use Case Diagram là bản đồ, không phải bản thiết kế. Đừng vẽ luồng dữ liệu, đừng vẽ màn hình. Chi tiết thuộc về specification dạng văn bản.
Mẹo vàng: Viết Main Flow bằng câu chủ động, chủ ngữ rõ ràng (luân phiên "Khách hàng..." và "Hệ thống..."), mỗi bước một hành động. Cách viết này tự nhiên ép bạn thấy được nơi tương tác diễn ra và nơi nào có thể phát sinh lỗi.
Bài tập thực hành
Bài 1 — Phân tích actor. Cho hệ thống "App đặt lịch khám bệnh online" (kiểu Medpro). Hãy liệt kê tối thiểu 4 actor, phân loại primary/supporting, và giải thích vì sao mỗi supporting actor là cần thiết.
Bài 2 — Viết Use Case Specification đầy đủ. Chọn use case "Đặt lịch khám với bác sĩ". Viết bản đặc tả theo template: ID, actor, precondition, postcondition, trigger, Main Flow (tối thiểu 6 bước), tối thiểu 2 Alternative Flow và 3 Exception Flow, kèm ít nhất 2 Business Rules. Gợi ý exception: bác sĩ kín lịch, thanh toán phí khám thất bại, khách hủy sát giờ.
Bài 3 — Vận dụng quan hệ. Trong hệ thống đặt lịch trên, "Đặt lịch", "Đổi lịch", "Hủy lịch" đều cần bước "Gửi thông báo cho bác sĩ". Hãy vẽ phác use case diagram dùng <<include>> cho phần dùng chung này, và thêm một use case <<extend>> cho tình huống "Nhắc lịch trước 1 giờ" (chỉ chạy khi khách bật nhắc nhở).
Bài 4 — Tự phản biện. Đưa bản đặc tả ở Bài 2 cho một người bạn không học kỹ thuật đọc. Ghi lại mọi câu hỏi họ đặt ra. Mỗi câu hỏi chưa trả lời được trong tài liệu là một lỗ hổng yêu cầu mà bạn vừa phát hiện sớm.
Tóm tắt
Use Case Modeling là nghệ thuật kể câu chuyện hệ thống có đầu, có cuối và có cả những ngã rẽ trục trặc. Những điểm cốt lõi cần nhớ:
- Use case = actor + tương tác + mục tiêu có giá trị. Không phải thao tác lẻ, không phải cả hệ thống.
- Actor gồm con người và hệ thống ngoài; phân biệt primary (khởi xướng) và supporting (được gọi tới). Mỗi supporting actor thường là một điểm tích hợp cần lên kế hoạch.
- Use Case Diagram cho bức tranh tổng quan với association, include, extend, generalization. Đừng nhầm hướng mũi tên include và extend.
- Use Case Specification mới là nơi giá trị thực sự nằm. Main Flow là phần dễ; Alternative và Exception Flow mới là nơi BA chứng minh đẳng cấp.
- Tách logic chung bằng
<<include>>để tài liệu dễ bảo trì; tách con số và điều kiện thành Business Rules có mã.