Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

D-Bài 22 — Sequence Diagram cho integration spec

Đã đọc 0/13 mục · còn khoảng 13 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Mở đầu — vì sao bài này quan trọng

Khi bạn còn là developer, bạn thường nhìn một tích hợp (integration) qua lăng kính code: gọi hàm này, await response kia, parse JSON, retry nếu lỗi. Nhưng khi bạn ngồi vào ghế BA, bạn phải mô tả luồng tích hợp đó cho nhiều người không đọc code: tech lead của đối tác, QA, project manager, đôi khi cả khách hàng phía Nhật hay Singapore. Nếu bạn viết một đoạn văn dài lê thê kiểu "đầu tiên hệ thống A gọi sang B, B kiểm tra rồi gọi tiếp C, nếu C trả về lỗi thì A phải...", chắc chắn người đọc sẽ rối và mỗi người hiểu một kiểu.

Đây chính là lúc Sequence Diagram (sơ đồ tuần tự) toả sáng. Nó là công cụ trực quan mạnh nhất để mô tả thứ tự thời gian của các tương tác giữa nhiều hệ thống, dịch vụ, hoặc thành phần. Một sequence diagram tốt thay thế cho ba trang mô tả bằng chữ, và quan trọng hơn, nó không cho phép mơ hồ: ai gọi ai, gọi gì, theo thứ tự nào, đồng bộ hay bất đồng bộ — tất cả đều phải hiện rõ trên giấy.

Là dev chuyển sang BA, bạn có một lợi thế cực lớn ở bài này: bạn đã hiểu request/response, đồng bộ/bất đồng bộ, webhook, message queue. Nhiều BA thuần business phải học những khái niệm này một cách vất vả. Việc của bạn chỉ là học cách biểu diễn chúng theo chuẩn UML để cả team cùng đọc được. Bài này sẽ giúp bạn làm chủ kỹ năng đó — một trong những vũ khí "đắt giá" nhất khi bạn làm spec tích hợp.

Khái niệm cốt lõi

Sequence Diagram là gì và khi nào dùng

Sequence Diagram là một loại sơ đồ trong UML mô tả các đối tượng (hệ thống, service, người dùng) tương tác với nhau theo trình tự thời gian từ trên xuống dưới. Trục dọc biểu diễn thời gian; trục ngang là các bên tham gia. Bạn đọc nó như đọc một kịch bản sân khấu: nhân vật nào nói gì, với ai, vào lúc nào.

Bạn nên rút sequence diagram ra dùng trong ba tình huống chính:

  • Spec tích hợp giữa 2+ hệ thống. Ví dụ hệ thống đặt hàng của bạn cần tích hợp cổng thanh toán VNPay, hoặc gọi API của Giao Hàng Nhanh để tạo vận đơn. Mỗi bước gọi qua lại là một mũi tên rõ ràng.
  • Document thứ tự các API call. Khi một thao tác nghiệp vụ cần gọi nhiều API liên tiếp (ví dụ: lấy token, xác thực, rồi mới gọi API nghiệp vụ), thứ tự là sống còn. Sequence diagram khoá chặt thứ tự đó.
  • Giải thích luồng bất đồng bộ (async). Webhook, callback, message queue, event-driven — đây là chỗ chữ viết bất lực nhất. Một mũi tên đứt nét cho callback nói rõ hơn nửa trang văn.

Các thành phần (element) bạn phải nắm

Lifeline (đường đời). Mỗi bên tham gia được vẽ bằng một hình chữ nhật ở trên cùng (tên hệ thống/actor) và một đường kẻ dọc đứt nét kéo xuống dưới. Đường dọc này là "lifeline" — nó đại diện cho sự tồn tại của đối tượng đó theo thời gian. Ví dụ: Mobile App, API Gateway, Payment Service, VNPay, Database.

Actor. Người dùng hoặc hệ thống bên ngoài khởi xướng luồng, thường vẽ bằng hình người que ở đầu trái. Ví dụ "Khách hàng" bấm nút thanh toán.

Message (thông điệp) — phần quan trọng nhất. Là các mũi tên ngang nối giữa các lifeline. Có vài loại bạn cần phân biệt rõ:

  • Synchronous message (đồng bộ): mũi tên với đầu mũi đặc (filled arrowhead). Bên gọi chờ phản hồi rồi mới đi tiếp. Ví dụ: POST /create-order.
  • Return message (phản hồi): mũi tên đứt nét, đầu mũi hở. Đây là response trả về. Ví dụ: 200 OK { orderId: 123 }.
  • Asynchronous message (bất đồng bộ): mũi tên đầu mũi hở/mảnh (open arrowhead), bên gọi không chờ. Dùng cho gửi message vào queue, bắn event, gọi webhook. Ví dụ: publish OrderCreated event.
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 đối tượng đang xử lý một việc gì đó. Nó giúp người đọc thấy "lúc này service đang bận làm gì".

Combined fragment (khung điều kiện). Đây là thứ nâng sequence diagram của bạn từ "ổn" lên "chuyên nghiệp". Là một khung chữ nhật bao quanh một nhóm message, có nhãn ở góc trái trên:

  • alt — alternative (rẽ nhánh if/else). Ví dụ: nếu thanh toán thành công thì..., ngược lại thì...
  • opt — optional (làm hoặc không). Ví dụ: nếu khách có mã giảm giá thì áp dụng.
  • loop — lặp lại. Ví dụ: thử lại gọi API tối đa 3 lần.
  • par — parallel (chạy song song). Ví dụ: đồng thời gửi email và SMS.
Note (ghi chú). Ô vuông gập góc để chú thích thêm điều kiện, timeout, hay business rule mà mũi tên không diễn đạt hết.

Sequence diagram khác Use Case và Activity Diagram thế nào

Đừng nhầm lẫn. Use Case mô tả chức năng gì hệ thống cung cấp (cấp cao, không có thứ tự kỹ thuật). Activity Diagram mô tả luồng nghiệp vụ/quy trình dạng flowchart. Còn Sequence Diagram tập trung vào ai gọi ai, theo thứ tự nào, qua interface nào — nó là cấp độ kỹ thuật nhất, hoàn hảo cho integration spec. Bài này chỉ nói về sequence diagram; đừng để bị cuốn sang vẽ flowchart nghiệp vụ.

Tình huống thực tế

Ví dụ 1: Tích hợp thanh toán VNPay cho sàn TMĐT (bối cảnh Việt Nam)

Giả sử bạn là BA tại một startup TMĐT ở TP.HCM, tên gọi "ChợNhanh", đang xử lý khoảng 5.000 đơn/ngày. Team cần spec luồng thanh toán qua VNPay cho đối tác dev và QA. Trước đây dev mô tả bằng chat Slack, kết quả là QA test thiếu case "thanh toán thành công nhưng webhook về trễ", gây ra 30–40 đơn/ngày bị treo trạng thái "đang xử lý".

Bạn vẽ sequence diagram như sau (mô tả dạng văn bản):

  • Khách hàng → ChợNhanh Web: bấm "Thanh toán" (sync)
  • ChợNhanh Web → Order Service: POST /orders tạo đơn trạng thái PENDING (sync) → return orderId
  • Order Service → VNPay: redirect kèm chữ ký vnp_SecureHash (sync)
  • Khách hàng → VNPay: nhập thông tin thẻ, xác thực OTP (sync)
  • Khung alt:
- [Thanh toán thành công] VNPay ⇢ Order Service: webhook IPN (async, mũi tên đứt) → Order Service cập nhật trạng thái PAID → return 200 - [Thất bại/huỷ] VNPay ⇢ Order Service: webhook với responseCode != 00 → giữ PENDING/đánh CANCELLED
  • Note: "Nếu sau 15 phút không nhận IPN, cron job query vnp_TransactionStatus để đối soát."
Bài học rút ra: Chính cái khung alt và cái note về timeout 15 phút đã làm lộ ra case mà trước đây cả team bỏ sót. QA đọc xong viết thêm 2 test case đối soát, và tỷ lệ đơn treo giảm về gần 0. Sequence diagram không chỉ để "đẹp" — nó ép bạn nghĩ tới mọi nhánh.

Ví dụ 2: Luồng async với message queue tại một fintech ở Singapore

Một công ty fintech khu vực Đông Nam Á (gọi là "PayLink") xử lý chuyển tiền liên ngân hàng. Bạn — BA có nền dev — cần spec luồng xử lý giao dịch dùng kiến trúc event-driven với Kafka. Đây là chỗ developer-turned-BA toả sáng, vì BA thuần thường không nắm khái niệm "fire and forget" của queue.

Luồng bạn vẽ:

  • Mobile App → Transfer API: POST /transfers (sync) → return 202 Accepted { transferId, status: PROCESSING }
  • Transfer API ⇢ Kafka (topic: transfer.requested): publish event (async, mũi tên hở)
  • Khung par (song song):
- Fraud Service ⇠ consume event → chấm điểm rủi ro - Ledger Service ⇠ consume event → ghi sổ tạm
  • Fraud Service ⇢ Kafka (topic: fraud.checked): publish kết quả (async)
  • Khung alt:
- [score < 70] Settlement Service xử lý chuyển tiền → ⇢ publish transfer.completed - [score >= 70] chuyển sang Manual Review Queue
  • Notification Service ⇠ consume transfer.completed ⇢ push notification cho Mobile App (async)
Bài học rút ra: Điểm mấu chốt mà sequence diagram làm rõ là: API trả về 202 ngay lập tức (status PROCESSING), còn kết quả thật đến sau qua notification. Nếu không vẽ ra, frontend dev rất dễ code kiểu "chờ response để hiện thành công" — sai hoàn toàn với mô hình async. Mũi tên hở (async) và khối par đã truyền tải đúng bản chất "không chờ, xử lý song song" mà chữ viết không làm nổi.

Ví dụ 3: Tích hợp đối tác giao vận với offshore client Nhật

Một công ty outsourcing ở Hà Nội nhận dự án cho khách Nhật, tích hợp hệ thống bán hàng với 3 đối tác giao vận (GHN, GHTK, Viettel Post). Khách Nhật yêu cầu spec cực kỳ chi tiết, song ngữ. Bạn vẽ một sequence diagram cho luồng "tạo vận đơn" dùng pattern retry:

  • Order Service → Shipping Adapter: createShipment(orderId, carrier) (sync)
  • Khung loop [tối đa 3 lần, mỗi lần cách 2 giây]:
- Shipping Adapter → GHN API: POST /shipping/order/create (sync) - Khung alt: [timeout/5xx] → tiếp tục loop; [2xx] → break
  • Khung alt:
- [thành công] return trackingCode - [hết 3 lần vẫn lỗi] → ghi DLQ (dead-letter), trả FAILED để nhân viên xử lý tay

Bài học rút ra: Khối loop mô tả retry policy là thứ khách Nhật đánh giá rất cao — họ vốn coi trọng xử lý lỗi. Trong buổi review, vì diagram quá rõ, cả buổi họp song ngữ rút từ 90 phút xuống 40 phút. Một sequence diagram tốt còn là công cụ giao tiếp xuyên ngôn ngữ, vì hình vẽ ít bị hiểu sai hơn chữ.

Hướng dẫn từng bước

Đây là quy trình bạn có thể áp dụng ngay cho bất kỳ integration spec nào:

Bước 1 — Xác định phạm vi và các bên tham gia. Liệt kê mọi hệ thống/service/actor xuất hiện trong luồng. Đặt actor khởi xướng ở ngoài cùng bên trái, các hệ thống còn lại xếp theo thứ tự chúng được gọi (trái sang phải). Đừng đưa quá nhiều lifeline — 4 đến 6 là vừa đẹp; nhiều hơn nên tách thành nhiều diagram.

Bước 2 — Xác định "trigger" (sự kiện kích hoạt). Luồng bắt đầu từ đâu? Người dùng bấm nút? Một cron job chạy? Một event đến? Mũi tên đầu tiên phải xuất phát từ trigger này.

Bước 3 — Vẽ các message theo đúng thứ tự thời gian, từ trên xuống. Với mỗi tương tác, hỏi ba câu: (a) Ai gọi ai? (b) Gọi cái gì — tên API/method và tham số chính? (c) Đồng bộ hay bất đồng bộ? Chọn đúng loại mũi tên. Luôn vẽ kèm return message cho các call đồng bộ — đừng để người đọc đoán response là gì.

Bước 4 — Bọc các nhánh điều kiện bằng combined fragment. Quét lại luồng: chỗ nào có "nếu... thì..." → dùng alt. Chỗ nào "có thể có hoặc không" → opt. Chỗ nào lặp/retry → loop. Chỗ nào song song → par. Đây là bước phân biệt BA non tay với BA cứng tay.

Bước 5 — Thêm note cho những gì mũi tên không nói được. Timeout bao nhiêu giây? Business rule nào áp dụng? Idempotency key? Định dạng dữ liệu đặc biệt? Ghi chú vào.

Bước 6 — Review chéo với dev và QA. Đưa diagram cho một dev: "Theo cái này code được không?" Đưa cho QA: "Test được hết các nhánh không?" Nếu cả hai gật đầu, spec của bạn đã đạt.

Về công cụ: Bạn không cần phần mềm đắt tiền. Mermaid (cú pháp text, render trực tiếp trong Confluence/GitLab/Notion) là lựa chọn tuyệt vời cho dev-turned-BA vì bạn viết bằng code, dễ version control. PlantUML mạnh tương đương. Nếu cần kéo-thả, dùng draw.io (miễn phí) hoặc Lucidchart. Với Mermaid, một sequence diagram đơn giản chỉ là vài dòng:

sequenceDiagram
    actor KH as Khách hàng
    participant Web as ChợNhanh Web
    participant VNPay
    KH->>Web: Bấm thanh toán
    Web->>VNPay: Redirect + SecureHash
    VNPay-->>Web: IPN callback (200)

Lỗi thường gặp & mẹo

Lỗi 1 — Nhầm sync và async. Đây là lỗi phổ biến nhất và nguy hiểm nhất. Vẽ webhook/queue bằng mũi tên đồng bộ khiến dev hiểu sai là "phải chờ". Mẹo: cứ thấy webhook, callback, message queue, event → dùng mũi tên bất đồng bộ (đầu hở) và đứt nét. Tự hỏi "bên gọi có đứng chờ phản hồi không?" — không chờ thì là async.

Lỗi 2 — Quên return message. Vẽ POST /orders mà không vẽ gì trả về khiến QA không biết kỳ vọng response là gì. Mẹo: mọi call đồng bộ phải có một mũi tên đứt nét trả về, kèm nội dung như 200 { orderId } hoặc 400 ValidationError.

Lỗi 3 — Nhồi nhét quá nhiều vào một diagram. Một sequence diagram 30 message với 10 lifeline là cơn ác mộng. Mẹo: một diagram = một kịch bản/luồng. Tách "luồng thành công", "luồng thất bại" hoặc "luồng chính" và "luồng đối soát" ra riêng nếu cần.

Lỗi 4 — Bỏ qua nhánh lỗi. BA mới thường chỉ vẽ "happy path". Nhưng integration spec mà thiếu nhánh lỗi (timeout, 4xx, 5xx, mất kết nối) là spec dở. Mẹo: với mỗi external call, luôn hỏi "nếu nó fail/timeout thì sao?" và vẽ vào alt.

Lỗi 5 — Dùng tên mơ hồ trên mũi tên. "Gửi dữ liệu", "xử lý" — quá chung chung. Mẹo: ghi rõ tên endpoint/method và payload chính: POST /v2/shipments { orderId, address }. Spec tích hợp cần độ chính xác này.

Mẹo vàng: Hãy vẽ diagram cùng dev trong buổi grooming, đừng vẽ một mình rồi mới đưa. Khi vẽ cùng nhau, dev sẽ tự bật ra "à chỗ này còn case retry nữa" — và bạn bắt được requirement ẩn ngay tại chỗ.

Bài tập thực hành

Bài 1 — Cơ bản. Vẽ sequence diagram cho luồng đăng nhập bằng OTP qua SMS: Người dùng nhập số điện thoại → App gọi Auth Service (POST /otp/request) → Auth Service gọi nhà cung cấp SMS (ví dụ Twilio/eSMS) gửi mã → người dùng nhập OTP → App gọi POST /otp/verify → trả về JWT. Yêu cầu: phân biệt đúng sync/async, có đầy đủ return message, và dùng alt cho case OTP sai.

Bài 2 — Nâng cao (async). Bạn là BA cho một app gọi xe ở Việt Nam. Vẽ sequence diagram cho luồng "đặt chuyến": khách đặt → hệ thống publish event tìm tài xế → nhiều tài xế nhận push notification (song song) → tài xế đầu tiên chấp nhận → các tài xế khác bị huỷ notification → khách nhận thông tin tài xế. Yêu cầu: dùng par cho việc bắn notification song song, dùng mũi tên async cho event, và có note về timeout "nếu sau 60 giây không có tài xế nhận thì huỷ".

Bài 3 — Thực chiến. Lấy một tích hợp thật trong dự án/công ty bạn (hoặc tích hợp VNPay/MoMo nếu bạn chưa có dự án). Viết spec dạng sequence diagram bằng Mermaid, bao gồm ít nhất một loop (retry) và một alt (thành công/thất bại). Sau đó đưa cho một developer bạn quen và hỏi: "Đọc cái này code được không?" Ghi lại phản hồi của họ — đó là thước đo chất lượng spec của bạn.

Tóm tắt

Sequence Diagram là công cụ số một để spec tích hợp giữa các hệ thống, document thứ tự API call, và giải thích luồng bất đồng bộ — đúng ba tình huống bạn gặp thường xuyên nhất khi làm BA kỹ thuật. Các element cốt lõi cần nắm là: lifeline (đường đời của mỗi bên), message (mũi tên đồng bộ đầu đặc / bất đồng bộ đầu hở / return đứt nét), activation bar, và đặc biệt là combined fragment (alt, opt, loop, par) — thứ phân biệt một spec nghiệp dư với một spec chuyên nghiệp.

Là developer chuyển sang BA, bạn đã có sẵn nền tảng hiểu request/response, sync/async, webhook và queue. Việc còn lại chỉ là học cách biểu diễn chúng đúng chuẩn để cả dev, QA, PM và khách hàng cùng đọc được. Hãy nhớ quy trình 6 bước: xác định các bên → tìm trigger → vẽ message theo thứ tự → bọc điều kiện bằng fragment → thêm note → review chéo với dev và QA. Tránh các lỗi kinh điển: nhầm sync/async, quên return, nhồi nhét, bỏ nhánh lỗi, đặt tên mơ hồ.

Cuối cùng, hãy biến sequence diagram thành thói quen: mỗi khi đụng tới một tích hợp mới, phản xạ đầu tiên của bạn nên là mở Mermaid lên và vẽ. Đó là cách bạn dùng chính lợi thế dev của mình để trở thành một BA mà cả team kỹ thuật tin tưởng.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi