Mở đầu — vì sao bài này quan trọng
Hãy tưởng tượng bạn vừa vẽ xong một sơ đồ quy trình BPMN rất đẹp: đầy đủ Task, Gateway, Event, được sắp xếp gọn gàng trong các pool và lane. Bạn tự tin gửi cho team kỹ thuật để họ triển khai trên Camunda. Rồi một tuần sau, kỹ sư nhắn lại: "Anh ơi, sơ đồ này không chạy được, engine báo lỗi vì có đường nối từ task của khách hàng sang task của hệ thống nội bộ bằng nét liền." Bạn ngơ ngác — trông thì có sao đâu?
Vấn đề nằm ở chỗ bạn đã dùng sai loại đường nối. Trong BPMN, không phải đường nối nào cũng giống nhau. Có hai loại "đường nối" mang hai ý nghĩa hoàn toàn khác biệt: Sequence Flow (luồng tuần tự) và Message Flow (luồng thông điệp). Nhầm lẫn giữa chúng là một trong những lỗi phổ biến nhất của người mới học BPMN, và đáng tiếc là nó không chỉ làm sơ đồ "xấu" mà còn làm sơ đồ sai về mặt ngữ nghĩa, dẫn đến hiểu nhầm trong giao tiếp và lỗi khi tự động hóa.
Ở các bài trước, bạn đã học về Pool và Lane (Bài 12), về Event, Activity và Gateway (Bài 13–17). Tất cả những phần tử đó là các "hộp" và "nút". Nhưng một sơ đồ quy trình chỉ thực sự có ý nghĩa khi các phần tử được nối với nhau đúng cách. Bài 18 này chính là về "chất keo" gắn kết mọi thứ lại: các đối tượng kết nối (Connecting Objects). Hiểu rõ Sequence Flow và Message Flow là điều kiện bắt buộc để sơ đồ của bạn vừa đọc được bởi con người, vừa thực thi được bởi máy.
Khái niệm cốt lõi
Trong BPMN 2.0, có ba loại đối tượng kết nối chính: Sequence Flow, Message Flow và Association. Hai loại đầu là trọng tâm của bài này. Điểm mấu chốt cần nhớ ngay từ đầu là: mỗi loại đường nối nói lên một loại quan hệ khác nhau giữa hai phần tử.
Sequence Flow — luồng tuần tự bên trong một pool
Sequence Flow được vẽ bằng đường nét liền với mũi tên đầu đặc (mũi tên được tô đầy màu đen).
Ý nghĩa của nó là: "Sau khi làm xong việc A thì làm tiếp việc B." Nói cách khác, Sequence Flow biểu diễn thứ tự thực thi (order of execution) của các hoạt động trong cùng một quy trình. Đây là xương sống của mọi sơ đồ quy trình.
Hai đặc tính quan trọng nhất của Sequence Flow:
Thứ nhất, nó chỉ được nối giữa hai flow object nằm trong CÙNG một pool. Một flow object là Event, Activity (Task/Sub-process) hoặc Gateway. Bạn không bao giờ được dùng Sequence Flow để vượt qua biên của một pool sang pool khác. Lý do sẽ rõ hơn khi ta nói về Message Flow.
Thứ hai, Sequence Flow mang "token". Đây là khái niệm cực kỳ quan trọng (sẽ được đào sâu trong Bài 26 về token semantics). Bạn hãy hình dung token như một "viên bi" hoặc "đốm sáng" di chuyển dọc theo các đường nét liền. Khi quy trình bắt đầu, một token xuất hiện tại Start Event. Token chạy theo Sequence Flow từ phần tử này sang phần tử khác. Tại mỗi Gateway, token có thể được chia ra (split) hoặc gộp lại (join). Khi token đi đến End Event, nó biến mất. Token chính là cách BPMN mô hình hóa "luồng điều khiển" (control flow) — tức là tại một thời điểm, quy trình đang chạy đến đâu. Vì token chỉ chạy trên Sequence Flow, nên ta nói Sequence Flow biểu diễn execution path (đường thực thi).
Một chi tiết kỹ thuật: Sequence Flow có thể gắn điều kiện (Conditional Sequence Flow), thường xuất phát từ một Gateway, ví dụ "nếu giá trị đơn hàng > 50 triệu thì đi nhánh này". Ngoài ra còn có Default Flow (vẽ với một gạch chéo nhỏ ở gốc) — nhánh mặc định khi không điều kiện nào khác đúng. Nhưng dù có điều kiện hay không, bản chất nó vẫn là luồng tuần tự mang token trong cùng một pool.
Message Flow — luồng thông điệp giữa các participant
Message Flow được vẽ bằng đường nét đứt (gạch đứt) với mũi tên đầu rỗng (mũi tên trống, không tô đen), và thường có một hình tròn nhỏ rỗng ở điểm xuất phát.
Ý nghĩa của nó hoàn toàn khác: Message Flow biểu diễn sự trao đổi thông điệp giữa hai participant khác nhau. Một participant trong BPMN được biểu diễn bằng một pool. Vì vậy, Message Flow luôn bắc cầu giữa hai pool khác nhau (hoặc giữa một pool với một phần tử bên trong pool khác).
Điểm khác biệt then chốt: Message Flow KHÔNG mang token. Nó không nói về thứ tự thực thi nội bộ của một quy trình, mà nói về việc "ai gửi gì cho ai". Ví dụ: khách hàng gửi đơn đặt hàng cho công ty; công ty gửi hóa đơn cho khách hàng; hệ thống thanh toán gửi xác nhận cho ngân hàng. Mỗi mũi tên nét đứt là một thông điệp băng qua ranh giới giữa các tổ chức/hệ thống độc lập.
Message Flow có thể nối:
- Từ pool (biên ngoài) sang pool khác.
- Từ một flow object (thường là Task hoặc Message Event) trong pool này sang một flow object trong pool khác.
- Từ một flow object sang biên của một pool khác (khi pool kia là "black box" — hộp đen không thể hiện chi tiết bên trong).
So sánh trực diện hai loại đường nối
Để bạn ghi nhớ dễ dàng, đây là bảng đối chiếu:
| Tiêu chí | Sequence Flow | Message Flow |
|---|---|---|
| Hình thức | Nét liền, mũi tên đặc | Nét đứt, mũi tên rỗng, tròn rỗng ở gốc |
| Nối ở đâu | Trong cùng một pool | Giữa hai pool khác nhau |
| Mang token? | Có | Không |
| Biểu diễn | Thứ tự thực thi (control flow) | Trao đổi thông điệp (communication) |
| Có điều kiện? | Có thể (conditional, default) | Không |
Một lưu ý về Association
Để hoàn thiện bức tranh "Connecting Objects", còn loại thứ ba là Association — vẽ bằng nét chấm (dotted line). Association không mang token cũng không phải thông điệp; nó chỉ dùng để gắn các Artifact (như Annotation — ghi chú, hoặc Data Object) với các phần tử khác. Phần này sẽ được nói kỹ ở Bài 19 và Bài 20, nên ở đây bạn chỉ cần phân biệt: Association là nét chấm phụ trợ, không liên quan đến luồng điều khiển hay giao tiếp giữa các bên.
Tình huống thực tế
Ví dụ 1: Tiki và quy trình xử lý đơn hàng
Hãy lấy một sàn thương mại điện tử như Tiki làm bối cảnh. Khi bạn mô hình hóa quy trình "Xử lý đơn hàng", bạn thường có ít nhất hai participant: Khách hàng và Tiki (hệ thống bán hàng). Mỗi participant là một pool riêng.
Trong pool "Tiki", quy trình nội bộ chạy như sau: Nhận đơn → Kiểm tra tồn kho → (Gateway: còn hàng?) → Xác nhận đơn → Đóng gói → Bàn giao vận chuyển → Kết thúc. Tất cả các bước này được nối với nhau bằng Sequence Flow nét liền, vì chúng diễn ra tuần tự bên trong tổ chức Tiki, và một token chạy dọc theo chúng để biểu diễn "đơn hàng đang ở giai đoạn nào".
Còn giữa pool "Khách hàng" và pool "Tiki", có các trao đổi thông điệp:
- Khách hàng gửi "Đặt hàng" → Task "Nhận đơn" của Tiki (Message Flow nét đứt).
- Task "Xác nhận đơn" của Tiki gửi "Email xác nhận" → Khách hàng (Message Flow).
- Sau khi giao xong, Tiki gửi "Yêu cầu đánh giá" → Khách hàng (Message Flow).
Bài học: Token không được phép "nhảy" từ pool này sang pool khác. Khi cần thể hiện việc một bên kích hoạt bên kia, bạn dùng Message Flow chạm vào một Message Start Event hoặc Message Catch Event của pool nhận. Đây cũng là cách BPMN engine hiểu được "khi nhận được thông điệp X thì khởi động/tiếp tục quy trình".
Ví dụ 2: Quy trình giải ngân tại một ngân hàng số Việt Nam
Giả sử một ngân hàng số (kiểu Timo hay Cake) mô hình hóa quy trình "Phê duyệt khoản vay tiêu dùng nhỏ". Ở đây có ba participant: Khách hàng, Ngân hàng (bộ phận tín dụng), và CIC (Trung tâm Thông tin Tín dụng Quốc gia — hệ thống tra cứu điểm tín dụng).
Bên trong pool "Ngân hàng": Nhận hồ sơ → Kiểm tra sơ bộ → Tra cứu CIC → (Gateway: điểm tín dụng đạt?) → Phê duyệt/Từ chối → Giải ngân. Đây toàn bộ là Sequence Flow, một token chạy qua từng bước, và tại Gateway token rẽ nhánh theo kết quả điểm tín dụng.
Trao đổi với bên ngoài là Message Flow:
- Khách hàng gửi "Hồ sơ vay" → Ngân hàng.
- Task "Tra cứu CIC" của Ngân hàng gửi "Truy vấn điểm tín dụng" → pool CIC (vẽ dưới dạng black box).
- CIC trả "Kết quả điểm tín dụng" → Ngân hàng.
- Ngân hàng gửi "Thông báo kết quả" → Khách hàng.
Bài học: Message Flow là công cụ tự nhiên để thể hiện tích hợp giữa quy trình của bạn và các hệ thống bên ngoài (API của đối tác, cổng thanh toán, cơ quan nhà nước). Khi bạn thấy một hệ thống bên ngoài, hãy phản xạ ngay: "Đây là một pool riêng, và tôi nối tới nó bằng Message Flow, không phải Sequence Flow."
Ví dụ 3: Lỗi nhầm lẫn làm hỏng dự án tự động hóa
Một công ty logistics tại TP.HCM (gọi là VietExpress) thuê một team BA vẽ lại quy trình "Xử lý khiếu nại giao hàng" để tự động hóa trên nền tảng BPM. Bản vẽ ban đầu có một pool duy nhất tên "VietExpress", nhưng bên trong lại trộn lẫn các bước của bộ phận Chăm sóc khách hàng, bộ phận Kho, và cả thao tác của khách hàng — tất cả nối bằng nét liền.
Khi đưa vào Camunda, engine cố gắng tạo một token chạy xuyên suốt từ "khách hàng gửi khiếu nại" cho đến "kho kiểm tra hàng". Vấn đề: làm sao engine "ép" khách hàng thực hiện một bước trong token flow của VietExpress? Không thể. Bước của khách hàng đáng lẽ phải nằm ở một pool khác và được kết nối bằng Message Flow.
Đội kỹ thuật mất gần hai ngày để gỡ rối, cuối cùng phải tách lại thành ba pool và thay toàn bộ các đường nối vượt biên thành Message Flow. Sau khi sửa, sơ đồ không chỉ chạy được mà còn rõ ràng hơn hẳn — ai cũng thấy ngay đâu là trách nhiệm của khách hàng, đâu là của VietExpress.
Bài học: Phân biệt đúng hai loại đường nối không phải chuyện "làm đẹp" — nó ảnh hưởng trực tiếp đến chi phí và tiến độ khi tự động hóa. Vẽ sai từ đầu khiến phải làm lại; vẽ đúng giúp sơ đồ vừa là tài liệu giao tiếp, vừa là bản thiết kế thực thi.
Hướng dẫn từng bước
Khi bạn cần quyết định dùng loại đường nối nào giữa hai phần tử, hãy đi qua quy trình tư duy sau:
- Xác định mỗi phần tử thuộc pool nào. Trước khi nối, hãy nhìn rõ phần tử nguồn và phần tử đích đang nằm trong pool nào. Nếu bạn chưa chia pool, hãy quay lại làm việc đó trước (xem Bài 12).
- Hỏi: hai phần tử có cùng pool không?
- Với Sequence Flow, kiểm tra hướng và tính hợp lệ. Mũi tên phải đi đúng chiều thực thi. Lưu ý: Start Event không có Sequence Flow đi vào nó; End Event không có Sequence Flow đi ra khỏi nó.
- Với Message Flow, gắn vào đúng điểm tiếp nhận. Đầu nhận của Message Flow lý tưởng là một Message Event (Message Start, Message Catch Intermediate) hoặc một Receive Task. Đầu gửi thường là một Send Task hoặc Message Throw Event. Nếu pool đích là black box, cứ nối vào biên pool.
- Đặt nhãn (label) cho Message Flow. Luôn ghi rõ thông điệp là gì: "Đơn đặt hàng", "Hóa đơn", "Kết quả CIC"... Message Flow không có nhãn sẽ làm người đọc bối rối không biết bên kia gửi cái gì.
- Rà soát lại toàn sơ đồ. Quét mắt qua mọi đường nối: có nét liền nào vượt biên pool không? Có nét đứt nào nằm gọn trong một pool không? Cả hai đều là dấu hiệu lỗi cần sửa.
Lỗi thường gặp & mẹo
Lỗi 1 — Dùng Sequence Flow vượt qua biên pool. Đây là lỗi kinh điển. Nhớ: token không bao giờ rời khỏi pool của nó. Mẹo: hầu hết công cụ tốt (Camunda Modeler, Bizagi, Signavio) sẽ tự động chặn bạn vẽ nét liền vượt pool — nếu công cụ không cho bạn nối, đừng cố tìm cách "lách", hãy hiểu rằng nó đang nhắc bạn dùng Message Flow.
Lỗi 2 — Dùng Message Flow giữa hai phần tử cùng pool. Một số người lạm dụng nét đứt để biểu diễn "gửi thông tin" giữa hai bộ phận trong cùng công ty (hai lane khác nhau trong cùng pool). Sai! Giữa hai lane vẫn là cùng một pool, nên vẫn dùng Sequence Flow. Lane chỉ là sự phân chia trách nhiệm bên trong một participant, không phải ranh giới giao tiếp.
Lỗi 3 — Quên rằng Message Flow không mang token. Người mới hay nghĩ "thông điệp gửi đi thì quy trình bên nhận tự chạy tiếp như một mạch liên tục". Không phải vậy. Message Flow chỉ kích hoạt một sự kiện (Message Event) ở bên nhận; bên nhận có token riêng của nó. Hai pool là hai luồng token độc lập, chỉ "bắt tay" qua thông điệp.
Lỗi 4 — Lane và Pool bị nhầm với nhau. Hãy nhớ: nhiều lane bên trong một pool = một participant với nhiều vai trò → Sequence Flow. Nhiều pool = nhiều participant độc lập → Message Flow giữa chúng.
Mẹo nhận dạng nhanh khi đọc sơ đồ của người khác: Nhìn vào kiểu nét. Nét liền mũi tên đặc = "thứ tự công việc". Nét đứt mũi tên rỗng = "thư từ qua lại giữa các bên". Chỉ riêng việc phân biệt được hai kiểu nét này đã giúp bạn đọc hiểu 80% logic giao tiếp của bất kỳ sơ đồ collaboration nào.
Mẹo thực hành: Khi vẽ một quy trình có nhiều bên tham gia, hãy vẽ khung pool và các Message Flow trước, rồi mới điền chi tiết Sequence Flow bên trong từng pool sau. Cách này giúp bạn không bị "lậm" vào chi tiết một pool mà quên mất bức tranh giao tiếp tổng thể.
Bài tập thực hành
Bài tập 1 — Phân loại đường nối. Cho các cặp phần tử sau, hãy xác định nên dùng Sequence Flow hay Message Flow:
- a) Task "Kiểm tra tồn kho" → Gateway "Còn hàng?" (cùng pool Tiki)
- b) Khách hàng "Thanh toán" → Task "Ghi nhận thanh toán" (khác pool)
- c) Lane "Kế toán" gửi sang Lane "Thủ kho" trong cùng pool "Công ty ABC"
- d) Task "Gửi truy vấn" của Ngân hàng → pool "CIC" (black box)
Bài tập 2 — Vẽ sơ đồ collaboration. Dùng draw.io hoặc Bizagi Modeler (miễn phí), vẽ quy trình "Đặt bàn nhà hàng" với hai pool: Khách hàng và Nhà hàng. Yêu cầu:
- Bên trong pool Nhà hàng có ít nhất 4 bước nối bằng Sequence Flow, trong đó có một Gateway "Còn bàn trống?".
- Có ít nhất 3 Message Flow giữa hai pool: khách gửi yêu cầu đặt bàn, nhà hàng gửi xác nhận, nhà hàng gửi nhắc lịch trước giờ hẹn.
- Mỗi Message Flow phải có nhãn rõ ràng.
Tóm tắt
Bài 18 xoay quanh "chất keo" gắn kết mọi phần tử trong sơ đồ BPMN: các đối tượng kết nối. Hai loại quan trọng nhất là Sequence Flow và Message Flow, và việc phân biệt chúng là kỹ năng nền tảng không thể bỏ qua.
Sequence Flow là nét liền, mũi tên đặc, chỉ nối các phần tử trong cùng một pool, mang token để biểu diễn thứ tự thực thi (control flow). Nó trả lời câu hỏi: "Làm xong việc này thì làm gì tiếp theo?"
Message Flow là nét đứt, mũi tên rỗng với hình tròn nhỏ ở gốc, nối giữa hai pool khác nhau, không mang token, biểu diễn việc trao đổi thông điệp giữa các participant độc lập. Nó trả lời câu hỏi: "Bên nào gửi gì cho bên nào?"
Quy tắc vàng cần khắc cốt ghi tâm: trong cùng pool dùng Sequence Flow, giữa hai pool dùng Message Flow — không có ngoại lệ. Nhầm lẫn hai loại này không chỉ làm sơ đồ sai về ngữ nghĩa mà còn gây lỗi nghiêm trọng khi tự động hóa, như ví dụ VietExpress đã cho thấy. Nắm vững bài này, bạn đã có nền móng để bước tiếp sang các chủ đề nâng cao hơn về Data Objects (Bài 19), Artifacts (Bài 20) và đặc biệt là token semantics (Bài 26) — nơi khái niệm token mà ta vừa làm quen sẽ được mổ xẻ chi tiết.