Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn là Technical BA trong một dự án thanh toán ví điện tử. Một buổi sáng, đội vận hành báo: "Có 2.000 giao dịch nạp tiền bị treo ở trạng thái PENDING suốt đêm qua." Lập tức, ba đội kéo vào phòng họp: backend, đối tác ngân hàng, và đội ví. Mỗi người kể một phiên bản khác nhau về "luồng nạp tiền chạy thế nào". Backend nói họ đã gọi ngân hàng. Đội ngân hàng nói họ đã callback về. Nhưng không ai chỉ được ra: ở bước thứ mấy thì giao dịch bị kẹt?
Đây chính là khoảnh khắc một Sequence Diagram (sơ đồ tuần tự) trở thành vũ khí mạnh nhất của Technical BA. Nó là loại sơ đồ thể hiện ai gọi ai, theo thứ tự nào, gửi cái gì, nhận lại cái gì — theo trục thời gian từ trên xuống dưới. Khác với flowchart (chỉ vẽ logic rẽ nhánh) hay sơ đồ kiến trúc (chỉ vẽ các khối hệ thống đứng cạnh nhau), sequence diagram cho bạn thấy cuộc đối thoại giữa các thành phần diễn ra như một kịch bản sân khấu.
Với Technical BA, kỹ năng này không phải để "đẹp tài liệu". Nó là cách bạn buộc cả lập trình viên, kiến trúc sư và đối tác phải thống nhất một sự thật chung trước khi viết code. Một sequence diagram tốt giúp phát hiện thiếu sót thiết kế — như quên xử lý timeout, quên trường hợp callback thất bại — ngay từ giai đoạn phân tích, khi việc sửa chỉ tốn vài dòng vẽ thay vì vài tuần fix production. Bài này sẽ dạy bạn đọc, vẽ và dùng sequence diagram đúng cách trong bốn tình huống cốt lõi: tài liệu hóa tương tác API, giải thích luồng phức tạp cho dev, review thiết kế tích hợp, và truy vết sự cố.
Khái niệm cốt lõi
Các thành phần của một Sequence Diagram
Một sequence diagram được tạo nên từ vài yếu tố đơn giản nhưng giàu ý nghĩa:
- Participant (đối tượng tham gia): Mỗi cột dọc là một thành phần — có thể là người dùng (Actor), một ứng dụng (Mobile App), một service (Payment Service), một cơ sở dữ liệu (Database), hoặc một hệ thống bên thứ ba (VNPAY Gateway). Mỗi participant có một lifeline — đường kẻ dọc kéo dài xuống thể hiện sự tồn tại của nó theo thời gian.
- Message (thông điệp): Mỗi mũi tên ngang là một lời gọi. Mũi tên đặc, liền nét (→) thường là lời gọi đồng bộ (synchronous) — bên gọi đứng chờ. Mũi tên nét đứt (⇠) là phản hồi trả về (return). Mũi tên đầu rỗng hoặc nét mảnh thể hiện lời gọi bất đồng bộ (asynchronous) — bên gọi không chờ mà đi tiếp.
- Activation bar (thanh kích hoạt): Hình chữ nhật mỏng nằm trên lifeline, thể hiện khoảng thời gian một participant đang "bận" xử lý một yêu cầu.
- Combined fragment (khối điều kiện): Đây là phần nâng cao nhưng cực kỳ giá trị với BA. Các khung bao quanh một nhóm message với nhãn ở góc trên:
alt — rẽ nhánh điều kiện (if/else): ví dụ "nếu OTP đúng → tiếp tục; nếu sai → trả lỗi".
- opt — bước tùy chọn, chỉ chạy khi điều kiện đúng.
- loop — lặp lại, ví dụ "thử lại tối đa 3 lần".
- par — các nhánh chạy song song.Đọc theo trục thời gian
Quy tắc vàng: đọc từ trên xuống dưới là đọc theo thời gian. Message ở phía trên xảy ra trước message ở phía dưới. Đây là điểm khiến sequence diagram dễ hiểu hơn mọi đoạn văn mô tả luồng — não người vốn quen với câu chuyện có trình tự "đầu tiên… sau đó… cuối cùng".
Khi nào dùng Sequence Diagram?
Là Technical BA, bạn nên rút sequence diagram ra trong bốn tình huống:
- Tài liệu hóa tương tác API: Khi một tính năng cần gọi nhiều API qua nhiều hệ thống, sequence diagram cho thấy thứ tự gọi và dữ liệu truyền giữa chúng rõ hơn mọi bảng mô tả.
- Giải thích luồng phức tạp cho lập trình viên: Khi luồng có nhiều nhánh, retry, callback — một bức hình ăn đứt mười đoạn văn.
- Review thiết kế tích hợp: Trước khi tích hợp với đối tác (ngân hàng, ví, ERP), vẽ sequence diagram giúp hai bên soi ra điểm chưa khớp về giao thức, timeout, hay xử lý lỗi.
- Truy vết sự cố (troubleshoot): Khi production lỗi, đặt sequence diagram lên cạnh log thực tế, bạn dò được chính xác message nào không xảy ra như thiết kế.
Tình huống thực tế
Ví dụ 1 — Luồng nạp tiền ví điện tử qua cổng VNPAY (tài liệu hóa API)
Bối cảnh: Một startup fintech tại TP.HCM xây ví điện tử "MoMoo" (giả định). Tính năng nạp tiền từ thẻ ngân hàng qua cổng VNPAY có 4 thành phần: Mobile App, Wallet Service, VNPAY Gateway, và Wallet Database. BA được giao viết spec cho luồng này.
Diễn giải: BA vẽ sequence diagram với trình tự:
- Mobile App → Wallet Service:
POST /topup(số tiền 500.000đ). - Wallet Service → Database: tạo bản ghi giao dịch trạng thái
PENDING. - Wallet Service → VNPAY Gateway: tạo URL thanh toán, trả về cho App.
- App hiển thị trang VNPAY, người dùng nhập OTP.
- (async) VNPAY Gateway → Wallet Service: callback
IPNbáo kết quả. - Khối
alt: nếu callbacksuccess→ cập nhật giao dịch thànhSUCCESS, cộng tiền; nếufailed→ cập nhậtFAILED.
loop job đối soát chạy mỗi 5 phút để truy vấn trạng thái từ VNPAY (reconciliation).Bài học: Chính hành động vẽ từng mũi tên buộc BA phải tự hỏi "bước này nếu thất bại thì sao", và phát hiện lỗ hổng thiết kế callback timeout — đúng cái lỗ hổng gây ra 2.000 giao dịch treo ở đầu bài. Sequence diagram không chỉ ghi lại thiết kế, nó lộ ra những gì còn thiếu.
Ví dụ 2 — Đăng nhập có xác thực OTP (giải thích luồng cho dev)
Bối cảnh: Một ngân hàng số tại Hà Nội triển khai đăng nhập 2 lớp: mật khẩu + OTP qua SMS. Team có một dev junior mới vào, đọc tài liệu mô tả dạng văn xuôi nhưng cài đặt sai thứ tự — sinh OTP trước cả khi kiểm tra mật khẩu, gây lỗ hổng bảo mật cho phép kẻ tấn công làm cạn quota SMS.
Diễn giải: BA dựng lại luồng bằng sequence diagram để buổi review không còn mơ hồ:
- App → Auth Service: gửi username + password.
- Khối
altđầu tiên: Auth Service kiểm tra mật khẩu với Database. Nếu sai → trả lỗi ngay, dừng. Nếu đúng → mới đi tiếp. - Auth Service → SMS Provider (Viettel/VNPT): gửi yêu cầu OTP.
loop(tối đa 3 lần): người dùng nhập OTP; nếu sai thì cho nhập lại; quá 3 lần → khóa 5 phút.- OTP đúng → Auth Service phát hành token, trả về App.
alt, không được đặt trước. Dev junior hiểu ngay sai ở đâu mà không cần ai giải thích dài dòng.Bài học: Với luồng có nhánh và lặp, sequence diagram dùng alt và loop biến một mô tả dễ hiểu nhầm thành một kịch bản không thể hiểu sai. Thứ tự message trên giấy chính là thứ tự code phải chạy.
Ví dụ 3 — Tích hợp đặt vé với đối tác hàng không (review thiết kế & truy vết sự cố)
Bối cảnh: Một nền tảng du lịch (kiểu Traveloka) tích hợp đặt vé với API của một hãng bay. Trong buổi review thiết kế trước khi code, BA và kiến trúc sư của hai bên ngồi lại với sequence diagram đặt vé:
- App → Booking Service: yêu cầu giữ chỗ.
- Booking Service → Airline API:
holdghế (giữ 10 phút). - App → Payment Service: thanh toán.
- Booking Service → Airline API:
confirmxuất vé.
confirm ở bước 4 bị timeout thì sao? Khách mất tiền mà không có vé." Đây là một lỗi nghiêm trọng mà không ai để ý cho đến khi nhìn vào trình tự message.Hai bên thống nhất bổ sung: khối alt cho bước 4 — nếu confirm thất bại → tự động hoàn tiền (refund) và ghi log cảnh báo. Họ cũng thêm cơ chế idempotency key để nếu retry confirm thì không bị xuất hai vé.
Ba tháng sau khi lên production, có sự cố thật: một số khách báo bị trừ tiền nhưng chưa thấy vé. Đội vận hành lấy đúng sequence diagram này, đặt cạnh log, và truy ngay được: lời gọi confirm ở bước 4 trả về HTTP 504 do mạng đối tác chập chờn — nhưng nhánh refund đã hoạt động đúng, tiền được hoàn trong 2 phút. Nhờ diagram, họ giải thích cho khách và quản lý chỉ trong 10 phút thay vì điều tra cả ngày.
Bài học: Sequence diagram phục vụ cả vòng đời — review trước khi code để bắt thiếu sót, và truy vết sau khi lỗi để định vị nhanh. Một bức diagram tốt là "bản đồ" để dò log thực tế.
Hướng dẫn từng bước
Đây là quy trình 7 bước để Technical BA dựng một sequence diagram chất lượng:
- Xác định phạm vi (scope) của luồng. Chọn một kịch bản cụ thể, ví dụ "nạp tiền qua VNPAY thành công", chứ không phải "toàn bộ chức năng ví". Một diagram chỉ nên kể một câu chuyện.
- Liệt kê các participant. Hỏi: ai khởi đầu luồng (thường là Actor hoặc App), những service nào tham gia, database nào, hệ thống bên thứ ba nào? Sắp xếp chúng từ trái sang phải theo thứ tự xuất hiện. Đừng nhồi quá 6-7 cột — quá nhiều sẽ rối.
- Vẽ message của luồng chính (happy path) trước. Đi tuần tự từ message đầu tiên đến cuối cùng cho trường hợp mọi thứ suôn sẻ. Ghi rõ tên endpoint và dữ liệu chính trên mũi tên:
POST /topup {amount: 500000}.
- Phân biệt đồng bộ và bất đồng bộ. Lời gọi nào bên gọi phải chờ kết quả (sync, mũi tên liền)? Lời gọi nào fire-and-forget hoặc callback (async, mũi tên đứt/mảnh)? Callback của VNPAY là async — vẽ sai sẽ hiểu nhầm cả luồng.
- Bổ sung các nhánh ngoại lệ bằng
alt/opt. Với mỗi message có thể thất bại, tự hỏi "nếu fail thì sao?". Thêm khốialtcho mỗi rẽ nhánh quan trọng: timeout, OTP sai, thanh toán thất bại. Đây là bước phân biệt BA giỏi với BA mới.
- Thêm
loopcho retry và polling. Các cơ chế thử lại, job đối soát định kỳ — gói trongloopvới điều kiện rõ ràng (tối đa bao nhiêu lần, mỗi bao lâu).
- Rà soát cùng dev/kiến trúc sư. Đưa diagram ra review, dùng nó làm trục cho cuộc thảo luận. Mỗi câu hỏi "còn trường hợp này thì sao?" là một message hoặc nhánh cần bổ sung.
sequenceDiagram
participant App
participant Wallet as Wallet Service
participant VNPAY
App->>Wallet: POST /topup {amount}
Wallet->>VNPAY: create payment URL
VNPAY-->>Wallet: payment URL
Wallet-->>App: return URL
VNPAY->>Wallet: IPN callback (async)
alt callback success
Wallet->>Wallet: update SUCCESS, cộng tiền
else callback failed
Wallet->>Wallet: update FAILED
end
Lỗi thường gặp & mẹo
Lỗi 1 — Chỉ vẽ happy path. Đây là lỗi phổ biến nhất. Diagram chỉ mô tả khi mọi thứ thành công, bỏ qua timeout, lỗi mạng, callback thất bại. Mẹo: với mỗi message external, luôn tự hỏi "nếu cái này không trả về thì sao?" và thêm nhánh alt.
Lỗi 2 — Nhầm đồng bộ với bất đồng bộ. Vẽ callback của cổng thanh toán bằng mũi tên sync khiến dev hiểu nhầm là Wallet Service đứng chờ, dẫn đến thiết kế sai. Mẹo: phân biệt rõ mũi tên liền (sync) và đứt/mảnh (async), ghi chú "callback" hoặc "webhook" cho rõ.
Lỗi 3 — Nhồi quá nhiều participant và message vào một diagram. Diagram 12 cột, 40 mũi tên thì không ai đọc nổi. Mẹo: tách thành nhiều diagram theo kịch bản — một cho luồng thành công, một cho luồng hủy, một cho đối soát.
Lỗi 4 — Lẫn lộn sequence diagram với flowchart. Cố nhét logic nghiệp vụ phức tạp (nhiều điều kiện lồng nhau) vào sequence diagram làm nó rối. Mẹo: nếu trọng tâm là "ai gọi ai" thì dùng sequence; nếu trọng tâm là "rẽ nhánh quyết định" thì dùng flowchart.
Lỗi 5 — Vẽ một lần rồi để diagram lỗi thời. Code đổi mà diagram không cập nhật thì còn nguy hiểm hơn không có. Mẹo: lưu diagram dạng Mermaid trong cùng repo với code, coi nó là một phần của tài liệu sống.
Mẹo vàng: Đặt tên message bằng đúng tên endpoint/sự kiện thật (POST /confirm, IPN callback), không viết chung chung "gửi yêu cầu". Như vậy dev đối chiếu diagram với code và với log production dễ dàng — đúng tinh thần một Technical BA.
Bài tập thực hành
Bài tập 1 (cơ bản): Vẽ sequence diagram cho luồng "đăng nhập bằng mật khẩu + OTP" trong Ví dụ 2. Yêu cầu: ít nhất 4 participant, một khối alt cho mật khẩu sai, một khối loop cho nhập OTP tối đa 3 lần. Dùng Mermaid.
Bài tập 2 (nâng cao): Cho luồng đặt vé hàng không ở Ví dụ 3, hãy vẽ phiên bản có xử lý ngoại lệ đầy đủ: bổ sung nhánh confirm timeout → tự động refund, và loop retry confirm với idempotency key. Viết kèm 2-3 câu giải thích vì sao cần idempotency key.
Bài tập 3 (thực chiến): Lấy một tính năng trong dự án thật của bạn (hoặc tự nghĩ: ví dụ "hủy đơn hàng và hoàn tiền trên sàn TMĐT"). Liệt kê participant, vẽ happy path, rồi tự hỏi 5 câu "nếu bước này fail thì sao?" và bổ sung đủ 5 nhánh ngoại lệ. So sánh diagram trước và sau — bạn đã phát hiện được lỗ hổng thiết kế nào?
Tóm tắt
Sequence diagram là công cụ thể hiện ai gọi ai, theo thứ tự nào, gửi nhận cái gì theo trục thời gian từ trên xuống. Với Technical BA, nó tỏa sáng trong bốn tình huống: tài liệu hóa tương tác API, giải thích luồng phức tạp cho dev, review thiết kế tích hợp, và truy vết sự cố. Các thành phần cốt lõi gồm participant, message (sync/async), activation bar, và các khối alt/opt/loop/par để diễn tả nhánh và lặp.
Giá trị lớn nhất không nằm ở bức hình đẹp, mà ở quá trình vẽ buộc bạn đặt câu hỏi "nếu fail thì sao" — chính câu hỏi đó phát hiện ra callback timeout của VNPAY, thứ tự sai của OTP, và rủi ro mất tiền không có vé. Hãy luôn vẽ happy path trước, rồi bổ sung nhánh ngoại lệ; phân biệt rõ đồng bộ với bất đồng bộ; dùng đúng tên endpoint thật; và giữ diagram luôn cập nhật như một tài liệu sống. Khi bạn thành thạo, sequence diagram sẽ trở thành ngôn ngữ chung giúp bạn, dev, kiến trúc sư và đối tác cùng nhìn về một sự thật — trước khi một dòng code được viết.