Last time we found out that only two of five BPMN gateways are absolutely necessary: XOR and AND.
Now let’s consider events. BPMN events are categorized by type (13 variants) and position (8 variants). Let’s consider event types:
1. None
Neither start nor end events are not strictly necessary - the diagram below is formally correct. Here Task 1 is the implicit start (no input flows), Task 2 is the implicit end (no output flows).
However such diagram looks incomplete and the question arises: was it done intentionally or it’s just a half-work? Therefore the good style supposes the start and end events to be always presented.
As for the intermediate none event, it depicts a process milestone. Not necessary yet useful and intuitive.
2. Link
If it came to the link event then probably it’s time for the decomposition - i.e. to leverage subprocesses. I’d recommend avoiding this event.
3. Timer
Helpful, intuitive, widely used in practice.
4. Conditional
Conditional event is helpful in certain scenarios yet it’s not the most intuitive. One of BPMN benefits is that, if used properly, it’s comprehensible by users without special trainings. It won’t be the case if conditional event is used.
The second issue is that it isn’t supported by most process engines. (In fact I haven’t seen a single one yet.)
But it isn’t that sad: conditional event can be replaced by a timer combined with XOR gateway:
= | ||
= |
Potential problems of such replacement are excessive engine load and messing the execution log.
5. Message
The major inter-process communication tool (along with data-based communications).
6. Signal
Signal is different from messages in two aspects. First, message is point-to-point while signal is publication-subscribtion. If one needs to connect a sender with a number of receivers then a signal can be replaced by a looped send task:
= |
Secondly, message assumes tight while signal - loose coupling. In order to instantiate process B from process A via a message, one needs to have process B model ready:
It’s not the case if signal is used - A and B models may be developed independently. What they they only need to know about each other is the signal name and the payload format, optionally:
When dealing with a complex system of processes, this signal feature becomes much valuable.
There is a workaround for signal in this scenario, too:
Here process A sets a flag in the datastore and process B checks it periodically. If flag isn’t set then B ends, otherwise it resets the flag and proceeds to the core job.
7. Terminate
8. Error
9. Escalation
These three events are more or less interchangeable:
= | ||
= |
Escalation has a valuable feature - it can create a new token and launch an async control flow in the outer process scope with the help of intermediate escalation initiator and non-interrupting boundary catcher.
10. Multiple
It’s relatively easy to workaround this event.
Catcher:
= |
Initiator:
= | = |
11. Parallel multiple
It’s quite easy to workaround the parallel multiple event if there are just two events:
= |
However in case of many events we’d run into the combinatorial explosion with this technique. Yet in practice I didn’t ever need even two start events. An if I did, I’d use CEP (Complex Event Processing) instead of BPMN.
12. Cancel
13. Compensation
Cancel and compensation events, transactional subprocess and compensation tasks are quite useful in a special scenario “all or nothing”. An example: I’m going to go to the conference. To be prepared, I need: 1) get my submission accepted by the conference committee, 2) book the plane, 3) book the hotel, 4) get my company’s approval on the expenses. It’d be better to perform all the activities in parallel - the less time available, the lower chances to succeed. Every single activity may not succeed and in this case a non-trivial set of compensating activities should be performed, e.g. if the submission was rejected and the plane was booked then the booking should be cancelled etc.
Transactions subprocesses and compensations provide an elegant solution to this kind of tasks. However they are relatively rare so one may not care about transactions and compensations most of the time.
Summary: from total number of 13 event types -
- 4 are essential - none, timer, message, terminate
- 2 are useful - signal, error
- 4 are for special cases - conditional, escalation, cancel, compensation
- 3 are practically useless - link, multiple, parallel multiple
Now let’s consider event categories by position, using message as example:
1. Start
2. End
3. Intermediate initiator
4. Intermediate catcher
These four are essential.
5. Attached event interrupting
Helpful, intuitive, popular.
6. Attached event non-interrupting
Not very intuitive. Can be workarounded, more or less:
= |
7. Event subprocess interrupting
8. Event subprocess non-interrupting
Event subprocesses are very similar to attached events. The major difference is that unlike event subprocess, one can’t attach an event to the top-level process. However it’s always possible to make a subprocess from the top-level flow:
Conclusions
Summing up, 5 event positions from 8 are essential: start, end, intermediate initiator and catcher, attached interrupting (this is actually BPMN 1.x subset).
If only essential plus useful types (6 totally) and essential positions (5 totally) are taken then there would be 30 combinations potentially possible from which only 19 are valid:
For the sake of comparison, the total number of valid event combinations in BPMN 2.0 is 63.
Hi Anatoly, great post (as always)!
[I would have argued in the gateway post that inclusive gateway is very useful too and it's not that difficult to explain - it's basically a parallel gateway that passes dark tokens on inactive branches - the scenario of having multiple options activated or not is very common in business and I have not found one single case where this could not be explained to a novice in as short a time as the rest of the gateways]
Several comments on your current post:
- conditional events are not very intuitive, but they could be helpful to model data conditionalities (especially as boundary events). Again, easy to explain (same cognitive load as XOR). BTW, camunda BPM supports conditional events.
- signal events are very helpful as described in your pattern, especially if you need complex orchestration of multiple instances - the downside being the load on the process engine. Messaging is not necessarily a tight coupling and could be a solution to the load problem, especially at scale (volume + velocity of signals event stream interrogations).
- error / escalation - we tend to use them with a touch of style: error is for technical handling, escalation is for business handling
- I found in practice that working around specific exotic events by means of subprocesses actually adds to the cognitive load, because it is less intuitive to discern process and sub-process boundaries and scopes, than deal with the same concepts at activity level.
Bogdan
Thanks for valuable input. We do not necessarily agree but your comments are always thoughts-provoking.
Camunda is great, thanks for another proof.
There is a subtle difference between conditional event and xor gateway: if the condition evaluates to true then the process will continue at the gateway but stop and wait at the event set to the same condition. Most people do not realize this I guess.
As for the error vs. escalation, we discussed it here http://mainthing.ru/item/446/ ages ago ) The difference between error and escalation is that the former behaves like terminator while the latter does not.
I agree that the subprocess workaround does add a load yet it’s more versatile and explicit so it’s worth to come through it once to get more freedom and preciseness.
Thanks Anatoly - my comment ref: conditional events and XOR was referring strictly to the similar cognitive burden of having to explain the two to users. I was not implying the two are syntactically similar.
As for the Error vs Escalation, I agree on their different End behavior - but isn’t this countering your point in this post that Error and Escalation events are more or less interchangeable?
That’s why I wrote “more or less” instead of “fully”