Menu
ESC

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

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

Đang tải...

Bài 25 — Multi-instance — Parallel và Sequential

Business Process Mapping and BPMN Bài 25/60

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

Hãy tưởng tượng bạn đang vẽ quy trình "Phê duyệt hợp đồng" cho một công ty. Hợp đồng cần được duyệt bởi ba người: Trưởng phòng Pháp chế, Giám đốc Tài chính và Tổng Giám đốc. Bạn sẽ vẽ thế nào? Nếu vẽ ba task riêng "Duyệt bởi Pháp chế" → "Duyệt bởi Tài chính" → "Duyệt bởi TGĐ" thì sơ đồ phình to, và tệ hơn: nếu mai mốt thêm một người duyệt nữa thì bạn phải sửa lại toàn bộ sơ đồ.

Đây chính là lúc Multi-instance (đa thực thể) trở nên cực kỳ giá trị. Multi-instance cho phép bạn diễn đạt ý "việc này được thực hiện nhiều lần, mỗi lần cho một đối tượng khác nhau" chỉ bằng một ký hiệu activity duy nhất. Số lần lặp có thể là cố định (3 người duyệt) hoặc động (duyệt bởi tất cả thành viên hội đồng — mà số lượng chỉ biết được lúc chạy).

Trong toàn bộ khóa học, đây là một trong những khái niệm BPMN bị hiểu sai nhiều nhất. Nhiều analyst nhầm Multi-instance với Loop (vòng lặp tuần tự đơn giản), hoặc nhầm Parallel Multi-instance với Parallel Gateway. Hiểu đúng bài này, bạn sẽ vẽ được những quy trình thực tế phức tạp — như xử lý từng dòng (line item) trong đơn hàng, gửi thông báo cho từng khách hàng, thu thập báo giá từ nhiều nhà cung cấp — một cách gọn gàng và đúng chuẩn để engine có thể tự động chạy.

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

Multi-instance activity là một activity (Task hoặc Sub-process) được cấu hình để chạy thành N bản sao (instance), mỗi bản xử lý một phần tử trong một tập hợp dữ liệu. Nói nôm na: "làm việc này một lần cho mỗi món trong danh sách".

Marker — cách nhận biết bằng mắt

Multi-instance được đánh dấu bằng ba vạch nhỏ đặt ở cạnh dưới của hình activity:

  • Ba vạch dọc (|||)Parallel Multi-instance — các instance chạy đồng thời (song song).
  • Ba vạch ngang (≡)Sequential Multi-instance — các instance chạy lần lượt (cái này xong mới tới cái kia).
Mẹo ghi nhớ đơn giản: vạch dọc trông giống nhiều cột đứng cạnh nhau cùng lúc → song song; vạch ngang trông giống các tầng xếp chồng, đi từ trên xuống → tuần tự. Đừng nhầm với ký hiệu Loop (một mũi tên xoay tròn ↻) — Loop là lặp lại chính bản thân nó dựa trên điều kiện, còn Multi-instance là tạo ra nhiều bản chạy cho nhiều phần tử dữ liệu.

Parallel Multi-instance (song song)

Tất cả N instance được khởi tạo cùng lúc và chạy độc lập, song song với nhau. Engine chỉ đi tiếp sau khi (thông thường) tất cả instance hoàn thành.

Ví dụ điển hình: gửi yêu cầu báo giá đến 5 nhà cung cấp cùng một lúc. Bạn không muốn chờ nhà cung cấp A trả lời rồi mới hỏi B; bạn gửi cả 5 ngay và chờ phản hồi về.

Đặc điểm quan trọng:

  • Thứ tự hoàn thành không xác định — instance nào xong trước thì xong, không theo trình tự.
  • Phù hợp khi các instance độc lập với nhau, không cái nào phụ thuộc kết quả cái kia.
  • Tổng thời gian ≈ thời gian của instance chậm nhất (chứ không phải tổng cộng).

Sequential Multi-instance (tuần tự)

Các instance chạy lần lượt từng cái một: instance thứ 2 chỉ bắt đầu sau khi instance thứ 1 kết thúc. Giống một vòng lặp for chạy qua từng phần tử.

Ví dụ: một quy trình phê duyệt phân cấp bắt buộc theo thứ tự — nhân viên xin nghỉ phép phải được Trưởng nhóm duyệt trước, rồi mới đến Trưởng phòng, rồi mới đến Giám đốc. Nếu Trưởng nhóm từ chối thì không cần làm phiền các cấp trên. Ở đây trình tự là bắt buộc nên phải dùng tuần tự.

Đặc điểm:

  • Tổng thời gian ≈ tổng thời gian của tất cả instance (vì chạy nối tiếp).
  • Phù hợp khi các instance phụ thuộc thứ tự, hoặc khi tài nguyên hạn chế (chỉ một người làm được, không thể chia ra).

Bốn tham số cấu hình bắt buộc nắm

Khi triển khai trên engine (như Camunda — sẽ học sâu ở Bài 31), một Multi-instance cần khai báo:

  • Loop Cardinality / Collection — số lần lặp. Hoặc là một số cố định (ví dụ 3), hoặc một biểu thức trỏ tới một danh sách (ví dụ ${danhSachNhaCungCap}) — engine sẽ tạo đúng một instance cho mỗi phần tử trong danh sách.
  • Element Variable — tên biến đại diện cho phần tử hiện tại trong mỗi instance (ví dụ nhaCungCap), để bên trong task biết "lần này đang xử lý ai".
  • Completion Condition — điều kiện dừng sớm. Ví dụ: "chỉ cần 3 trong 5 người duyệt là đủ, dừng luôn các instance còn lại". Đây chính là mẫu N-out-of-M rất hay dùng trong thực tế.
  • isSequentialtrue là tuần tự, false là song song.
Hiểu bốn tham số này là ranh giới phân biệt giữa người "biết vẽ ký hiệu" và người "biết thiết kế quy trình tự động chạy được".

Tình huống thực tế

Ví dụ 1 — Tiki: xử lý từng dòng hàng trong đơn (Parallel)

Bối cảnh: Một sàn thương mại điện tử kiểu Tiki nhận một đơn hàng gồm nhiều sản phẩm từ nhiều nhà bán (seller) khác nhau. Đơn của khách có thể có 4 món: 1 cuốn sách (kho Tiki), 1 chai dầu gội (seller A ở TP.HCM), 1 bộ đồ chơi (seller B ở Hà Nội), 1 chai nước hoa (kho Tiki). Mỗi món phải được đóng gói riêng vì xuất phát từ kho/seller khác nhau.

Diễn giải: Analyst thiết kế một Sub-process tên "Đóng gói gói hàng" được gắn marker Parallel Multi-instance. Collection là ${danhSachKienHang} (4 kiện), Element Variable là kienHang. Vì 4 kho/seller hoạt động độc lập, không cần chờ nhau, nên dùng song song: cả 4 lệnh đóng gói được phát đi cùng lúc. Khi cả 4 kiện đã đóng xong, quy trình mới chuyển sang bước "Gom kiện và bàn giao vận chuyển".

Nếu trước đây sàn này dùng cách vẽ 4 task riêng, thì với đơn có 10 món họ phải sửa sơ đồ — điều phi lý. Với Multi-instance, sơ đồ không đổi dù đơn có 2 món hay 50 món.

Bài học: Khi cùng một logic xử lý lặp lại trên một tập đối tượng có số lượng động và các phần tử độc lập, dùng Parallel Multi-instance. Sơ đồ gọn, và quan trọng hơn, engine tự co giãn theo dữ liệu thật.

Ví dụ 2 — Ngân hàng VPBank: thu thập báo giá thẩm định tài sản (Parallel + Completion Condition)

Bối cảnh: Khi khách hàng vay thế chấp bằng bất động sản, ngân hàng cần định giá tài sản. Để minh bạch, quy chế nội bộ yêu cầu gửi yêu cầu định giá đến 4 công ty thẩm định độc lập, nhưng chỉ cần nhận đủ 2 báo cáo là phòng tín dụng đã có thể lấy giá trung bình để xét duyệt — không cần chờ cả 4.

Diễn giải: Task "Nhận báo cáo định giá" được cấu hình Parallel Multi-instance với Collection 4 công ty. Điểm tinh tế nằm ở Completion Condition: ${soBaoCaoNhanDuoc >= 2}. Ngay khi 2 instance hoàn thành, engine kích hoạt điều kiện dừng, hủy 2 instance còn lại và đi tiếp. Đây chính là mẫu N-out-of-M giúp rút ngắn cycle time đáng kể: thay vì chờ công ty chậm nhất (có thể 5 ngày), quy trình chốt ngay khi đủ 2 báo cáo (có thể chỉ 2 ngày).

Một con số minh họa: nếu thời gian phản hồi trung bình của 4 công ty lần lượt là 2, 3, 4, 5 ngày, thì chờ-tất-cả mất 5 ngày, còn chờ-2-cái-nhanh-nhất chỉ mất 3 ngày — tiết kiệm 40% thời gian cho mỗi hồ sơ.

Bài học: Parallel Multi-instance kết hợp Completion Condition là vũ khí tối ưu thời gian cực mạnh khi bạn cần "đủ số lượng tối thiểu" chứ không cần "tất cả".

Ví dụ 3 — FPT Software: phê duyệt timesheet phân cấp (Sequential)

Bối cảnh: Trong một công ty phần mềm như FPT, bảng chấm công (timesheet) của lập trình viên trước khi tính lương phải qua chuỗi duyệt theo cấp: Team Lead → Project Manager → Delivery Director. Quy định là bắt buộc đúng thứ tự, và nếu Team Lead phát hiện sai và từ chối thì dừng ngay, không làm phiền các cấp trên.

Diễn giải: Task "Duyệt timesheet" dùng Sequential Multi-instance, Collection là danh sách người duyệt theo đúng thứ tự [TeamLead, PM, Director]. Vì isSequential = true, instance cho PM chỉ khởi tạo sau khi Team Lead đã duyệt xong. Completion Condition ${ketQua == 'TU_CHOI'} cho phép dừng cả chuỗi ngay khi bất kỳ cấp nào từ chối.

Nếu vô tình dùng Parallel ở đây sẽ sai nghiệp vụ nghiêm trọng: cả ba cấp nhận yêu cầu duyệt cùng lúc, Director có thể duyệt trước cả Team Lead — phá vỡ nguyên tắc phân cấp và làm phiền cấp cao một cách không cần thiết.

Bài học: Khi trình tự là bắt buộc hoặc các instance phụ thuộc lẫn nhau, luôn chọn Sequential. Đừng vì "song song nhanh hơn" mà hy sinh tính đúng đắn của nghiệp vụ.

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

Đây là quy trình suy nghĩ để áp dụng Multi-instance đúng:

Bước 1 — Phát hiện dấu hiệu lặp. Đọc kỹ mô tả nghiệp vụ và soi các cụm từ như "với mỗi", "từng", "tất cả", "mỗi nhà cung cấp", "mỗi dòng hàng", "mỗi thành viên". Đây là tín hiệu rõ ràng của Multi-instance. Nếu bạn thấy mình định copy-paste cùng một task nhiều lần, dừng lại — đó là lúc cần Multi-instance.

Bước 2 — Xác định tập dữ liệu (Collection). Hỏi: "Lặp trên cái gì?" Phải có một danh sách rõ ràng: danh sách nhà cung cấp, danh sách line item, danh sách người duyệt. Xác định luôn số lượng là cố định (biết trước) hay động (chỉ biết lúc chạy).

Bước 3 — Quyết định song song hay tuần tự. Tự đặt câu hỏi vàng: "Các instance có phụ thuộc thứ tự không? Cái sau có cần kết quả cái trước không?" Nếu không → Parallel (nhanh hơn). Nếu → Sequential.

Bước 4 — Chọn Task hay Sub-process. Nếu mỗi instance chỉ là một hành động đơn giản → Multi-instance Task. Nếu mỗi instance là cả một chuỗi bước (nhận, kiểm tra, xác nhận) → bọc thành Multi-instance Sub-process cho gọn.

Bước 5 — Xác định điều kiện dừng (nếu có). Có cần "đủ N là dừng" (N-out-of-M) không? Có cần "ai từ chối thì dừng cả chuỗi" không? Nếu có, khai báo Completion Condition.

Bước 6 — Gắn marker và đặt tên rõ ràng. Vẽ ba vạch dọc (parallel) hoặc ngang (sequential) dưới activity. Đặt tên động từ + danh từ số ít, ví dụ "Gửi yêu cầu báo giá" (chứ không phải "Gửi các yêu cầu") — vì marker đã ngụ ý "lặp cho từng cái" rồi.

Bước 7 — Khai báo biến và kiểm thử với dữ liệu thật. Đặt Element Variable rõ nghĩa, rồi thử với danh sách rỗng (0 phần tử), 1 phần tử, và nhiều phần tử để chắc chắn quy trình không kẹt.

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

Lỗi 1 — Nhầm Multi-instance với Parallel Gateway. Đây là lỗi kinh điển. Parallel Gateway (||| hình thoi — học ở Bài 16) chia luồng thành nhiều nhánh khác nhau chạy song song (ví dụ: "Kiểm tra tín dụng" VÀ "Kiểm tra pháp lý" — hai việc khác nhau). Còn Parallel Multi-instance chạy cùng một task nhiều lần cho nhiều dữ liệu khác nhau. Nguyên tắc: nhiều việc khác nhau → Gateway; cùng một việc lặp nhiều lần → Multi-instance.

Lỗi 2 — Nhầm với Loop marker. Loop (↻) lặp lại chính nó dựa trên một điều kiện và bản chất là tuần tự, đếm chưa biết trước ("làm lại cho tới khi đúng"). Multi-instance lặp trên một tập dữ liệu đã biết. Nếu bạn biết trước "lặp cho từng phần tử trong danh sách" → Multi-instance, không phải Loop.

Lỗi 3 — Quên xử lý tập rỗng. Nếu Collection rỗng (0 phần tử), Multi-instance sẽ tạo ra 0 instance và "đi xuyên qua" ngay. Đôi khi đây không phải điều bạn muốn (ví dụ đơn hàng không có món nào?). Hãy luôn cân nhắc thêm một Gateway kiểm tra danh sách rỗng trước đó.

Lỗi 4 — Lạm dụng Parallel khi tài nguyên có giới hạn. Vẽ "gọi 100 cuộc điện thoại song song" nghe thì đẹp, nhưng nếu chỉ có 2 nhân viên tổng đài thì thực tế không thể song song. Khi nguồn lực thực thi hữu hạn, Sequential phản ánh thực tế trung thực hơn — và tránh tạo kỳ vọng sai về cycle time.

Lỗi 5 — Quên Completion Condition khi nghiệp vụ cần dừng sớm. Nếu nghiệp vụ là "ai duyệt từ chối thì hủy" mà bạn không khai Completion Condition, engine sẽ ngoan ngoãn chờ tất cả instance xong — gây lãng phí và sai logic.

Mẹo vàng: Khi nhìn một Multi-instance, luôn tự trả lời được ba câu: Lặp trên cái gì? (Collection) — Song song hay tuần tự? (isSequential) — Khi nào dừng? (Completion Condition). Trả lời được ba câu này là bạn đã thiết kế đúng chuẩn engine-executable.

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

Bài 1 — Phân loại. Với mỗi tình huống dưới đây, hãy quyết định Parallel hay Sequential Multi-instance và giải thích ngắn:

  • (a) Gửi email xác nhận đặt vé cho 30 hành khách trong một đoàn du lịch.
  • (b) Phỏng vấn 3 ứng viên cuối, mỗi vòng phỏng vấn quyết định có gọi ứng viên tiếp theo hay không.
  • (c) Một hội đồng 7 thành viên bỏ phiếu, chỉ cần 4 phiếu thuận là thông qua.
Bài 2 — Vẽ sơ đồ. Vẽ BPMN cho quy trình: "Phòng mua hàng gửi yêu cầu báo giá đến tất cả nhà cung cấp đã đăng ký cho mặt hàng cần mua, nhận báo giá về, rồi chọn nhà cung cấp rẻ nhất." Xác định: đâu là Multi-instance, song song hay tuần tự, Collection là gì, có Completion Condition không.

Bài 3 — Sửa lỗi. Một bạn đồng nghiệp vẽ quy trình duyệt chi phí phân cấp (Nhân viên → Trưởng phòng → Kế toán trưởng) bằng Parallel Multi-instance. Hãy chỉ ra lỗi nghiệp vụ và đề xuất sửa.

Bài 4 — Thiết kế nâng cao. Cho tình huống Ví dụ 2 (VPBank, 4 công ty thẩm định, đủ 2 báo cáo là chốt). Hãy viết ra đầy đủ bốn tham số cấu hình: Collection, Element Variable, isSequential, Completion Condition.

Gợi ý đáp án Bài 1: (a) Parallel — 30 email độc lập, không phụ thuộc thứ tự. (b) Sequential — mỗi vòng quyết định có tiếp tục không, phụ thuộc thứ tự. (c) Parallel với Completion Condition soPhieuThuan >= 4.

Tóm tắt

Multi-instance là cách BPMN diễn đạt "làm một việc nhiều lần, mỗi lần cho một phần tử dữ liệu" bằng đúng một ký hiệu activity. Ghi nhớ cốt lõi:

  • Marker: ba vạch dọc = Parallel (song song, chạy cùng lúc); ba vạch ngang = Sequential (tuần tự, chạy lần lượt).
  • Parallel dùng khi các instance độc lập và bạn muốn nhanh — tổng thời gian bằng instance chậm nhất.
  • Sequential dùng khi có phụ thuộc thứ tự hoặc tài nguyên hữu hạn — tổng thời gian là tổng các instance.
  • Completion Condition cho phép dừng sớm theo mẫu N-out-of-M ("đủ là chốt"), giúp tối ưu cycle time đáng kể.
  • Đừng nhầm với Parallel Gateway (nhiều việc khác nhau) hay Loop (lặp theo điều kiện, không theo tập dữ liệu).
  • Khi thiết kế, luôn trả lời được: lặp trên cái gì, song song hay tuần tự, khi nào dừng — đó là chìa khóa để quy trình của bạn không chỉ đẹp trên giấy mà còn chạy được trên engine.
Nắm vững Multi-instance, bạn đã có trong tay một công cụ mạnh để mô hình hóa những quy trình thực tế phức tạp một cách gọn gàng, đúng chuẩn và sẵn sàng cho tự động hóa.