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 quy trình "Xử lý đơn hàng" cho công ty. Trên giấy mọi thứ trông rất đẹp: đơn hàng đến, kho kiểm tra, giao hàng. Nhưng đời thực không bao giờ chạy thẳng một đường như vậy. Khách hàng đặt đơn dưới 500 nghìn thì miễn phí ship hay không? Đơn trên 10 triệu thì có cần duyệt thủ công không? Khách VIP thì đi luồng ưu tiên hay luồng thường? Mỗi câu "nếu... thì..." đó chính là một điểm rẽ nhánh trong quy trình.
Và đây là lúc Gateway bước vào sân khấu. Trong toàn bộ ngôn ngữ BPMN, Gateway là thành phần quyết định dòng chảy (flow) của quy trình rẽ đi đâu. Nếu Task là "làm gì" và Event là "chuyện gì xảy ra", thì Gateway là "đi đường nào". Trong số tất cả các loại Gateway, Exclusive Gateway — hay còn gọi là XOR Gateway — là loại bạn sẽ dùng nhiều nhất, dễ đến 70-80% các điểm rẽ nhánh trong một quy trình thực tế đều là Exclusive.
Bài này tập trung riêng vào Exclusive Gateway. Các loại Gateway khác như Parallel (AND), Inclusive (OR), Event-based và Complex sẽ được trình bày ở Bài 16 và Bài 17. Ở đây, chúng ta sẽ mổ xẻ thật kỹ một loại duy nhất, vì nếu bạn nắm chắc Exclusive Gateway, bạn đã nắm được nền tảng tư duy rẽ nhánh — và nắm sai nó là một trong những nguyên nhân hàng đầu khiến mô hình BPMN bị lỗi logic hoặc thậm chí "treo" khi đem ra chạy bằng process engine.
Khái niệm cốt lõi
Exclusive Gateway là gì
Exclusive Gateway biểu diễn một quyết định rẽ nhánh độc quyền (mutually exclusive): tại điểm này, dòng chảy phải chọn đúng một và chỉ một đường để đi tiếp. "Exclusive" nghĩa là loại trừ lẫn nhau — chọn đường A thì không chọn đường B, và ngược lại. Đây chính là hiện thực hóa của câu lệnh if-else hoặc switch-case mà bất kỳ ai từng lập trình đều quen thuộc.
Từ "XOR" (eXclusive OR) trong logic học cũng mang đúng ý nghĩa này: trong các lựa chọn, chỉ một điều đúng được kích hoạt.
Ký hiệu
Exclusive Gateway được vẽ bằng một hình thoi (diamond). Bên trong hình thoi có một dấu × (chữ X). Đây là điểm cần ghi nhớ kỹ:
- Convention chuẩn (BPMN 2.0): hình thoi có dấu
×bên trong. - Convention cũ: hình thoi để trống (không có ký hiệu nào). Theo đặc tả BPMN, một Gateway để trống mặc định được hiểu là Exclusive Gateway.
×, người đọc sẽ bối rối không biết hai cái đó có khác nhau không. Lời khuyên của tôi với học viên: luôn vẽ dấu × một cách nhất quán trong mọi sơ đồ. Đừng để trống. Sự rõ ràng quan trọng hơn sự ngắn gọn.Hai vai trò: Split và Merge
Một Exclusive Gateway có thể đóng hai vai trò hoàn toàn khác nhau, và việc phân biệt chúng là kiến thức bản lề:
1. Split (rẽ nhánh / phân kỳ — diverging): Gateway có một Sequence Flow đi vào và nhiều Sequence Flow đi ra. Tại đây engine sẽ đánh giá điều kiện và chọn đúng một nhánh ra để token đi tiếp.
- Mỗi nhánh ra (trừ nhánh mặc định) phải gắn một điều kiện (condition expression), ví dụ
giá_trị_đơn > 10000000. - Engine đánh giá các điều kiện theo thứ tự, lấy nhánh đầu tiên có điều kiện đúng (
true). - Phải có một Default Flow (luồng mặc định) — được vẽ bằng một gạch chéo nhỏ ở đầu mũi tên — để dùng khi không điều kiện nào đúng. Đây là cái lưới an toàn cực kỳ quan trọng.
Điểm mấu chốt cần khắc cốt ghi tâm: Exclusive Merge KHÔNG chờ (no synchronization). Nó không đợi tất cả các nhánh cùng về. Token nào đến trước thì đi trước, đến sau thì đi sau — mỗi token kích hoạt nhánh ra một lần. Đây là sự khác biệt sống còn so với Parallel Gateway (sẽ học ở Bài 16), nơi Merge bắt buộc phải đợi đủ tất cả nhánh.
Token đi như thế nào
Hãy hình dung dòng chảy quy trình như một viên bi (gọi là token) lăn theo các mũi tên. Khi viên bi đến một Exclusive Gateway dạng Split, nó không tách ra thành nhiều viên — nó vẫn là một viên duy nhất, chỉ chọn một con đường để lăn tiếp. Đây là điểm khác biệt căn bản với Parallel Gateway, nơi một viên bi vào sẽ "nhân bản" thành nhiều viên cùng chạy song song. (Cơ chế token này được trình bày chi tiết ở Bài 26, nhưng bạn cần nắm trực giác cơ bản ngay từ giờ.)
Tình huống thực tế
Ví dụ 1 — Tiki: phân luồng duyệt đơn theo giá trị
Giả sử bộ phận vận hành của một sàn thương mại điện tử như Tiki thiết kế quy trình "Xác nhận đơn hàng". Sau khi khách đặt đơn, hệ thống cần quyết định: đơn nào tự động xác nhận, đơn nào phải có nhân viên duyệt tay.
Họ đặt một Exclusive Gateway sau Task "Nhận đơn hàng" với hai nhánh ra:
- Nhánh 1, điều kiện
giá_trị_đơn >= 5000000: đi tới Task "Nhân viên duyệt thủ công". - Nhánh 2 (Default Flow): đi tới Task "Tự động xác nhận".
Bài học: Khi tiêu chí phân luồng là loại trừ lẫn nhau (một đơn chỉ thuộc đúng một nhóm), Exclusive Gateway là lựa chọn chính xác. Và luôn đặt trường hợp phổ biến nhất (đơn giá trị nhỏ) làm Default Flow để tránh quên xử lý ngoại lệ.
Ví dụ 2 — Ngân hàng số: phê duyệt hồ sơ vay tiêu dùng
Một ngân hàng số (tạm gọi MB Bank Digital) xây quy trình thẩm định khoản vay tiêu dùng nhanh. Sau Task "Chấm điểm tín dụng tự động", họ đặt một Exclusive Gateway Split với ba nhánh dựa trên điểm số credit_score:
credit_score >= 750: nhánh "Duyệt tự động", giải ngân ngay.credit_score >= 500(và dưới 750): nhánh "Chuyển chuyên viên thẩm định".- Default Flow: nhánh "Từ chối tự động".
>= 750) và dừng lại — dù về mặt logic nó cũng thỏa >= 500. Vì là Exclusive, engine không xét tiếp các nhánh sau khi đã tìm thấy nhánh đúng đầu tiên. Nếu nhóm thiết kế vô tình đặt điều kiện >= 500 lên trước >= 750, thì mọi hồ sơ điểm cao cũng bị đẩy sang luồng thẩm định tay — một lỗi logic kinh điển khiến chuyên viên ngập trong hồ sơ lẽ ra nên duyệt tự động.Sau đó, cả ba nhánh đều cần ghi log và gửi thông báo cho khách. Thay vì lặp lại ba lần, họ dùng một Exclusive Gateway Merge để gộp ba nhánh về một, rồi nối tới Task "Gửi thông báo kết quả". Vì merge không chờ, hồ sơ nào xử lý xong trước thì gửi thông báo trước — đúng như mong muốn.
Bài học: Với Exclusive Gateway, thứ tự điều kiện quyết định kết quả. Hãy sắp xếp điều kiện chặt nhất (ngưỡng cao nhất) lên trước, hoặc viết điều kiện đầy đủ khoảng (>= 500 && < 750) để tránh phụ thuộc thứ tự.
Ví dụ 3 — Grab/Be: định tuyến khiếu nại khách hàng
Một nền tảng gọi xe như Be xây quy trình "Xử lý khiếu nại". Sau khi tiếp nhận, một Exclusive Gateway phân loại theo loại_khiếu_nại:
= "thanh toán": chuyển đội Tài chính.= "an toàn": chuyển đội An toàn (luồng ưu tiên).= "thái độ tài xế": chuyển đội Chăm sóc khách hàng.- Default Flow: chuyển đội Chăm sóc khách hàng tổng quát.
switch-case thuần túy: mỗi khiếu nại thuộc đúng một loại, đi đúng một đội. Default Flow ở đây cực kỳ giá trị — nó "bắt" mọi loại khiếu nại lạ chưa được phân loại (ví dụ một loại mới phát sinh) thay vì để token bị kẹt không biết đi đâu.Bài học: Khi phân loại theo một thuộc tính rời rạc (loại, hạng, trạng thái), Exclusive Gateway giúp sơ đồ gọn gàng và dễ bảo trì. Và Default Flow không phải tùy chọn cho vui — nó là tấm lưới chống "token bị treo".
Hướng dẫn từng bước
Khi bạn cần thêm một điểm rẽ nhánh Exclusive vào sơ đồ, hãy làm theo trình tự sau:
- Xác định câu hỏi quyết định. Viết ra một câu hỏi rõ ràng có thể trả lời bằng cách chọn đúng một phương án. Ví dụ: "Giá trị đơn hàng thuộc khoảng nào?". Thực tế, hãy đặt câu hỏi này làm nhãn (label) cho Gateway trên sơ đồ — người đọc sẽ hiểu ngay.
- Kiểm tra tính loại trừ. Tự hỏi: các phương án có thực sự loại trừ lẫn nhau không? Một đối tượng có thể rơi vào hai nhánh cùng lúc không? Nếu không thể — dùng Exclusive. Nếu có thể nhiều nhánh cùng đúng và bạn muốn chạy nhiều nhánh — đó là Inclusive (Bài 16), không phải Exclusive.
- Vẽ Gateway và đặt các nhánh ra. Vẽ hình thoi có dấu
×. Kéo các Sequence Flow ra tới các Task tiếp theo.
- Gắn điều kiện cho từng nhánh. Mỗi nhánh ra (trừ nhánh mặc định) gắn một condition expression rõ ràng. Đặt nhãn cho mũi tên (ví dụ "Đơn ≥ 5 triệu") để người đọc không cần mở thuộc tính kỹ thuật vẫn hiểu.
- Luôn khai báo một Default Flow. Chọn một nhánh làm mặc định và đánh dấu gạch chéo. Đây là nhánh chạy khi không điều kiện nào đúng. Bỏ qua bước này là nguyên nhân số một khiến quy trình "treo" khi chạy thật.
- Sắp xếp thứ tự điều kiện hợp lý. Vì engine lấy nhánh đúng đầu tiên, hãy đặt điều kiện cụ thể/chặt nhất lên trước, hoặc viết khoảng đầy đủ để không phụ thuộc thứ tự.
- Khi cần gộp lại, dùng Exclusive Merge. Nếu các nhánh sau đó cùng đi tới một bước chung, dùng một Exclusive Gateway Merge (nhiều vào, một ra) để gộp. Đừng kéo nhiều mũi tên đâm thẳng vào một Task — điều đó hợp lệ về cú pháp nhưng làm sơ đồ khó đọc; dùng Merge tường minh sẽ rõ ràng hơn.
- Kiểm tra cân bằng (balance). Mỗi Split nên có một Merge tương ứng để dòng chảy "đóng lại" gọn gàng. Sơ đồ cân bằng dễ đọc và ít lỗi hơn.
Lỗi thường gặp & mẹo
Lỗi 1 — Quên Default Flow. Bạn đặt ba điều kiện nhưng có một đầu vào không khớp cái nào. Với một số engine, token sẽ bị kẹt và quy trình báo lỗi runtime. Mẹo: luôn luôn có Default Flow. Coi nó như khối else bắt buộc.
Lỗi 2 — Điều kiện chồng lấp (overlap) mà không để ý thứ tự. Như ví dụ ngân hàng: >= 500 đặt trước >= 750 khiến hồ sơ điểm cao đi sai luồng. Mẹo: viết điều kiện thành các khoảng rời rạc rõ ràng, hoặc dùng cấu trúc ngưỡng giảm dần và đặt ngưỡng cao nhất lên đầu.
Lỗi 3 — Dùng Exclusive khi đáng lẽ phải dùng Parallel. Ví dụ: sau khi nhận đơn cần vừa kiểm kho vừa kiểm thanh toán cùng lúc. Đây là hai việc song song, không loại trừ — phải dùng Parallel Gateway (Bài 16). Nếu dùng Exclusive, bạn chỉ làm một trong hai. Mẹo: hỏi "các nhánh này chạy đồng thời hay chọn một?". "Chọn một" → Exclusive. "Cùng chạy" → Parallel.
Lỗi 4 — Trông đợi Exclusive Merge sẽ chờ đồng bộ. Nhiều người mới tưởng Merge sẽ đợi tất cả nhánh về rồi mới đi tiếp. Không! Exclusive Merge không chờ. Mỗi token đến đều kích hoạt ngõ ra một lần. Nếu bạn vô tình dùng nó để gộp các nhánh từ một Parallel Split, bạn sẽ tạo ra nhiều token chạy tiếp thay vì một — gây nhân đôi công việc. Mẹo: Parallel Split phải đi cặp với Parallel Merge; Exclusive Split đi cặp với Exclusive Merge.
Lỗi 5 — Đặt điều kiện trên mũi tên ra của một Parallel Gateway. Điều kiện chỉ có ý nghĩa với Exclusive (và Inclusive). Parallel bỏ qua mọi điều kiện. Mẹo: nếu nhánh ra cần điều kiện, đó là dấu hiệu bạn cần Exclusive chứ không phải Parallel.
Mẹo vàng — đặt nhãn câu hỏi cho Gateway. Một Gateway tốt luôn có nhãn dạng câu hỏi ("Đơn ≥ 5 triệu?", "Loại khiếu nại?") và mỗi nhánh ra có nhãn câu trả lời. Sơ đồ tự giải thích được mà không cần chú thích bên ngoài.
Bài tập thực hành
Hãy lấy giấy bút hoặc mở một công cụ như draw.io / Bizagi Modeler và làm bài sau:
Đề bài: Một phòng khám tư ở TP.HCM muốn mô hình hóa quy trình "Tiếp nhận bệnh nhân". Yêu cầu:
- Sau Task "Tiếp nhận thông tin", đặt một Exclusive Gateway phân luồng theo loại bệnh nhân:
- Chọn một nhánh làm Default Flow và giải thích vì sao bạn chọn nhánh đó.
- Sau khi cả ba luồng xử lý xong, tất cả cùng đi tới Task "Mời vào phòng khám". Hãy dùng một Exclusive Merge để gộp ba nhánh.
- Viết ra condition expression (dạng giả mã) cho từng nhánh ra của Gateway Split.
- Nếu một bệnh nhân vừa có BHYT vừa là ca cấp cứu, sơ đồ của bạn xử lý ra sao? Thứ tự điều kiện có quan trọng không? (Gợi ý: đặt điều kiện cấp cứu lên trên cùng.)
- Tại sao ở đây dùng Exclusive Merge mà không phải Parallel Merge? Điều gì sẽ xảy ra nếu bạn dùng nhầm Parallel Merge?
Tóm tắt
- Exclusive Gateway (XOR) biểu diễn quyết định rẽ nhánh loại trừ lẫn nhau: chọn đúng một và chỉ một nhánh. Đây là hiện thực của
if-else/switch-casetrong BPMN. - Ký hiệu là hình thoi có dấu
×. Convention cũ để trống cũng được hiểu là Exclusive, nhưng hãy luôn vẽ dấu×cho nhất quán và rõ ràng. - Có hai vai trò: Split (một vào, nhiều ra — chọn một nhánh theo điều kiện) và Merge (nhiều vào, một ra — gộp luồng).
- Exclusive Merge KHÔNG chờ đồng bộ. Mỗi token đến đều đi tiếp ngay. Đây là khác biệt cốt lõi với Parallel Gateway.
- Mỗi nhánh ra cần điều kiện rõ ràng; engine lấy nhánh đúng đầu tiên, nên thứ tự điều kiện quyết định kết quả.
- Luôn khai báo Default Flow — tấm lưới an toàn chống token bị treo.
- Phân biệt rõ với Parallel (cùng chạy) và Inclusive (nhiều nhánh có thể cùng đúng) ở Bài 16.