5 Wyjątki i podprocesy
Po spotkaniu: zapiszesz w tok zdarzenia graniczne przerywające i nieprzerywające (termin, błąd, eskalacja, wiadomość) · zbudujesz podproces i podproces zdarzeniowy z własnym początkiem i końcem · przeprowadzisz model przez podróż tok → BPMN → Camunda Modeler → tok i ocenisz, co się w niej zmieniło · Czas: Nauka 40 min, Wyzwanie 50 min
5.1 Nauka
Wyjątki w tekście
Na kursie BPMN wyjątki modelowaliśmy zdarzeniami granicznymi (boundary events), zob. rozdział 6 kursu BPMN. Kółko przyczepione do krawędzi zadania mówi: „jeśli w trakcie tej pracy coś się stanie, idź tą ścieżką”. W tok zdarzenie graniczne to osobny wiersz ze słowem boundary. O tym, do której czynności jest przyczepione, decyduje atrybut on=:
user odbior "Odbiór książki"
boundary termin "Minęło 7 dni" on=odbior timer=P7D
boundary przypomnienie-czas "Minęły 3 dni" on=odbior timer=P3D noninterrupting
Zdarzenie graniczne ma trzy części:
| Część | Przykład | Znaczenie |
|---|---|---|
on= |
on=odbior |
identyfikator czynności, na której krawędzi wisi zdarzenie |
| wyzwalacz | timer=P7D, error="Błąd zapisu", escalation="Trudna kwerenda", message="Odwołanie", signal="Zamknięcie czytelni" |
co uruchamia wyjątek |
flaga noninterrupting |
zadanie trwa dalej, a ścieżka wyjątku rusza równolegle |
Bez flagi noninterrupting zdarzenie jest przerywające: gdy zajdzie, zadanie zostaje odebrane. To ustawienie domyślne, tak jak w BPMN. Błąd (error=) jest zawsze przerywający. Zapis boundary … error="…" noninterrupting walidator odrzuci kodem E012.
Czas zapisujesz w formacie ISO 8601: P7D to 7 dni, PT2H to 2 godziny, P1M to miesiąc. Wartość z ukośnikiem, np. cykl R3/PT1H, piszesz w cudzysłowie.
Ze zdarzenia granicznego wychodzi zwykły przepływ sekwencji: flow termin -> odeslanie -> zwrocona. Do zdarzenia granicznego nic nie wchodzi, bo uruchamia je czynność, a nie poprzedni krok.
Przykład: odbiór książki z terminami
Książka zamówiona w innej bibliotece dotarła. Bibliotekarz rejestruje ją w systemie. Jeśli zapis się nie uda, rejestruje ją ręcznie. Czytelnik ma 7 dni na odbiór. Po 3 dniach dostaje przypomnienie, ale nadal może odebrać książkę. Po 7 dniach książka wraca do biblioteki udostępniającej.
tok 0.1 "Odbiór książki z wypożyczalni międzybibliotecznej"
pool biblioteka "Biblioteka uczelniana"
lane bibliotekarz "Bibliotekarz wypożyczalni międzybibliotecznej"
start dotarla "Książka dotarła"
service rejestracja "Rejestracja egzemplarza w systemie"
boundary blad-zapisu "Błąd zapisu" on=rejestracja error="Błąd zapisu"
user reczna "Rejestracja ręczna"
user powiadomienie "Powiadomienie czytelnika"
user odeslanie "Odesłanie książki"
end zwrocona "Książka zwrócona bibliotece udostępniającej"
lane czytelnik "Czytelnik"
user odbior "Odbiór książki"
boundary przypomnienie-czas "Minęły 3 dni" noninterrupting on=odbior timer=P3D
boundary termin "Minęło 7 dni" on=odbior timer=P7D
end odebrana "Książka odebrana"
lane system "System biblioteczny"
service przypomnienie "Wysłanie przypomnienia"
end przypomniano "Przypomnienie wysłane"
flow dotarla -> rejestracja -> powiadomienie -> odbior -> odebrana
flow blad-zapisu -> reczna -> powiadomienie
flow przypomnienie-czas -> przypomnienie -> przypomniano
flow termin -> odeslanie -> zwrocona
Rysunek 5.1: Odbiór książki: błąd zapisu oraz terminy przerywający i nieprzerywający.
Pobierz model (.tok) Pobierz eksport BPMN (.bpmn)
Sprawdź, jak opis przekłada się na tekst:
| Zdanie z opisu | Wiersz tok |
|---|---|
| „jeśli zapis się nie uda” | boundary blad-zapisu … on=rejestracja error="Błąd zapisu" |
| „po 3 dniach dostaje przypomnienie, ale nadal może odebrać” | boundary przypomnienie-czas … on=odbior timer=P3D noninterrupting |
| „po 7 dniach książka wraca” | boundary termin … on=odbior timer=P7D |
Zdarzenia graniczne deklarujesz w linii, w której mają być narysowane, zwykle w linii swojej czynności. Ścieżka wyjątku może prowadzić do innej linii, jak tu przypomnienie wysyłane przez system.
Podproces
Podproces (sub-process) to kilka kroków, które tworzą całość. W tok to słowo sub z blokiem. Wszystko, co jest wcięte pod nim, należy do podprocesu:
sub poszukiwania "Poszukiwania w zasobie"
start p-start
user inwentarze "Przegląd inwentarzy"
end p-koniec "Poszukiwania zakończone"
Zasady są te same co w BPMN:
- podproces ma własny start i własny koniec. Start wewnątrz zwykłego podprocesu nie ma wyzwalacza;
- przepływy sekwencji nie przekraczają granicy podprocesu. Proces główny łączy się z podprocesem jako całością:
flow zakres -> poszukiwania, a nie z jego wnętrzem.
Przepływy wnętrza podprocesu możesz zapisać razem z innymi na końcu dokumentu. tok sam rozpozna, że oba końce leżą w podprocesie. Jeśli połączysz element procesu głównego z elementem wnętrza podprocesu, dostaniesz błąd. Dla modelu, w którym start procesu prowadzi wprost do zadania wewnątrz podprocesu, tok check --lang pl wypisuje:
cross.tok:10: błąd R021: przepływ sekwencji s -> szukaj przekracza granicę procesu lub podprocesu
Na diagramie podproces jest rozwinięty: widać jego wnętrze w ramce. Elementy wnętrza nie należą do linii. Do linii należy cały podproces.
Eskalacja z podprocesu
Eskalacja to sygnał „ta sprawa wymaga decyzji wyżej”, ale bez przerywania pracy. Rzuca ją zdarzenie wewnątrz podprocesu, a łapie zdarzenie graniczne na jego krawędzi. Oba łączy ta sama nazwa eskalacji:
sub poszukiwania "Poszukiwania w zasobie"
...
throw trudnosc "Kwerenda wymaga decyzji kierownika" escalation="Trudna kwerenda"
...
boundary eskalacja "Trudna kwerenda" on=poszukiwania escalation="Trudna kwerenda" noninterrupting
Flaga noninterrupting na granicy oznacza, że poszukiwania trwają dalej, a kierownik równolegle podejmuje decyzję. Jeśli rzucisz eskalację, której nic nie łapie, walidator zgłosi ostrzeżenie W053.
Podproces zdarzeniowy
Podproces zdarzeniowy (event sub-process) uruchamia się w dowolnym momencie trwania procesu, gdy zajdzie jego zdarzenie początkowe. W tok to słowo eventsub. Jego blok zaczyna się zdarzeniem początkowym z wyzwalaczem:
eventsub wycofanie "Wycofanie wniosku"
start w-start "Wniosek wycofany" message="Wycofanie wniosku"
user zamkniecie "Zamknięcie sprawy"
end w-koniec "Sprawa zamknięta"
Podproces zdarzeniowy nie ma przepływów wchodzących ani wychodzących. Jego start jest domyślnie przerywający: kończy resztę procesu. Flaga noninterrupting na starcie (start … message="…" noninterrupting) sprawia, że podproces działa obok procesu głównego.
Przykład: kwerenda z podprocesem
Poniższy model łączy wszystkie konstrukcje: podproces z eskalacją, podproces zdarzeniowy wywoływany wiadomością od wnioskodawcy i zdarzenie końcowe terminate.
tok 0.1 "Kwerenda archiwalna z podprocesem"
pool archiwum "Archiwum Państwowe"
lane kancelaria "Kancelaria"
start wniosek "Wniosek o kwerendę wpłynął" message="Wniosek o kwerendę"
user rejestracja "Rejestracja wniosku"
xor zakres "Czy wniosek dotyczy zasobu archiwum?"
end bezprzedmiotowy "Wniosek bezprzedmiotowy" terminate
eventsub wycofanie "Wycofanie wniosku"
start w-start "Wniosek wycofany" message="Wycofanie wniosku"
user zamkniecie "Zamknięcie sprawy"
end w-koniec "Sprawa zamknięta"
lane archiwista "Archiwista"
sub poszukiwania "Poszukiwania w zasobie"
start p-start
user inwentarze "Przegląd inwentarzy"
xor znaleziono "Czy znaleziono akta?"
user akta "Analiza akt"
throw trudnosc "Kwerenda wymaga decyzji kierownika" escalation="Trudna kwerenda"
end p-koniec "Poszukiwania zakończone"
boundary eskalacja "Trudna kwerenda" noninterrupting on=poszukiwania escalation="Trudna kwerenda"
user odpowiedz "Przygotowanie odpowiedzi"
end wyslana "Odpowiedź wysłana" message="Odpowiedź na kwerendę"
lane kierownik "Kierownik oddziału"
user decyzja "Decyzja o dalszych poszukiwaniach"
end rozstrzygnieto "Sprawa rozstrzygnięta"
pool wnioskodawca "Wnioskodawca"
flow wniosek -> rejestracja -> zakres
flow zakres -> poszukiwania "tak"
flow zakres -> bezprzedmiotowy "nie"
flow poszukiwania -> odpowiedz -> wyslana
flow p-start -> inwentarze -> znaleziono
flow znaleziono -> akta "tak"
flow znaleziono -> trudnosc "nie"
flow trudnosc -> akta -> p-koniec
flow eskalacja -> decyzja -> rozstrzygnieto
flow w-start -> zamkniecie -> w-koniec
message wnioskodawca -> wniosek "Wniosek o kwerendę"
message wyslana -> wnioskodawca "Odpowiedź na kwerendę"
message wnioskodawca -> w-start "Wycofanie wniosku"
Rysunek 5.2: Kwerenda archiwalna: podproces z eskalacją i podproces zdarzeniowy.
Pobierz model (.tok) Pobierz eksport BPMN (.bpmn)
Flaga terminate przy end bezprzedmiotowy oznacza zdarzenie końcowe, które natychmiast kończy cały proces, także ścieżki równoległe. W tym modelu nie ma ich na tej gałęzi. W modelach z bramką równoległą terminate rozstrzyga, że po odrzuceniu wniosku żadna inna ścieżka nie będzie kontynuowana.
Kompensacja i wywołanie procesu
Dwie konstrukcje wystarczy na razie znać z nazwy:
| Zapis | Znaczenie |
|---|---|
boundary cofnij "Cofnięcie rezerwacji" on=rezerwacja compensate |
zdarzenie graniczne kompensacji na zadaniu |
user anulowanie "Anulowanie rezerwacji" compensation |
czynność kompensacyjna: cofa skutki wykonanej pracy, nie ma przepływów sekwencji |
throw kompensacja "Wycofanie zmian" compensate |
zdarzenie, które uruchamia kompensację |
call szkolenie "Organizacja szkolenia" process=organizacja-szkolenia |
czynność wywołania: uruchamia inny, osobno opisany proces |
Kompensacja przydaje się w procesach, w których coś trzeba „odkręcić”, np. anulować rezerwację sali, gdy szkolenie zostaje odwołane. Czynność wywołania pozwala opisać raz proces używany w wielu miejscach, np. obsługę płatności.
Podróż tok → BPMN → tok
Model tok nie zamyka cię w jednym narzędziu. Możesz go wyeksportować, poprawić w Camunda Modeler i wrócić do tekstu. Ta podróż ma trzy etapy:
- Eksport:
tok bpmn model.toktworzymodel.bpmnz układem diagramu. - Praca w Modelerze: otwierasz plik, zmieniasz model (przenosisz zadanie do innej linii, poprawiasz nazwę, dodajesz krok) i zapisujesz.
- Import:
tok import model.bpmn -o model2.tokzamienia plik BPMN z powrotem na tekst.
Jeśli w Modelerze nic nie zmienisz, import odtwarza dokładnie ten sam tekst. Sprawdziliśmy to na modelu odbioru książki: plik po podróży nie różni się od oryginału ani jednym znakiem.
Po zmianie w Modelerze porównaj oba pliki tekstowe, np. w VS Code. Zobaczysz tylko wiersze, których dotyczy zmiana. Na modelu odbioru książki przeniesiono w Modelerze zadanie „Powiadomienie czytelnika” do linii systemu i zmieniono jego nazwę. W imporcie:
- wiersz
user powiadomienie …przeszedł z linii bibliotekarza do linii „System biblioteczny” i ma nową etykietę; - linia „System biblioteczny” przesunęła się w tekście wyżej. Import układa linie w kolejności, w jakiej pojawiają się ich elementy w procesie. Teraz w tej linii jest zadanie wykonywane wcześnie;
- przepływy i pozostałe elementy się nie zmieniły.
Dwie rzeczy warto wiedzieć o imporcie:
- Układ diagramu nie wraca do tekstu. tok nie zapisuje współrzędnych, więc przesunięcie prostokąta w Modelerze nie zmienia modelu. Przy następnym
tok bpmnukład zostanie obliczony od nowa. To zamierzone: tekst przechowuje znaczenie, a rysunek jest widokiem. - Identyfikatory przepływów z Modelera. Gdy w Modelerze dorysujesz strzałkę, dostanie ona identyfikator typu
Flow_0x7k2ab. Import zachowuje go i drukuje przepływ jako osobny wiersz zid=…. Opcja--no-flow-idspomija identyfikatory przepływów i pozwala złożyć je z powrotem w łańcuchy. Używaj jej, gdy dalej pracujesz na tekście, a identyfikatory przepływów nie są ci potrzebne.
Import przyjmuje też pliki narysowane od zera w Modelerze, np. modele z kursu BPMN. Elementy spoza tok 0.1 (np. bramkę złożoną) pomija i wypisuje o nich ostrzeżenie.
5.2 Wyzwanie
Polecenie: zapisz w tok proces „Digitalizacja na zamówienie w bibliotece cyfrowej” z dwoma basenami, danymi i wyjątkami, a potem przeprowadź go przez podróż do Camunda Modeler i z powrotem.
Dane wejściowe: tabela kroków w opisie zadania Z2 (dodatek C). Proces znasz z kursu BPMN. Tym razem ma dodatkowo zamknięty basen „Zamawiający” i przepływy komunikatów.
Kroki:
- Ustal baseny, linie, typy elementów i wyjątki. Zwróć uwagę na trzy różne wyjątki: termin 14 dni, termin 5 dni i awarię skanera. Każdy ma inny charakter.
- Napisz
z2-digitalizacja.tok, sprawdź go (tok check --lang pl) i uporządkuj (tok fmt -w). - Wyeksportuj BPMN i SVG, otwórz model w Camunda Modeler i wprowadź zmianę opisaną w zadaniu.
- Zaimportuj zmieniony plik, porównaj teksty i opisz wynik w
z2-podroz.md.
Rezultat: pliki wymienione w opisie zadania Z2.
Praca: indywidualnie, bez narzędzi sztucznej inteligencji.
Czas: 50 minut na zajęciach. Zadanie dokończ przed spotkaniem 6.
Zadanie Z2. Model z basenami, danymi i wyjątkami oraz jego podróż przez BPMN (20%). Oddajesz model z2-digitalizacja.tok z eksportem BPMN i SVG, model po zmianie w Camunda Modeler zaimportowany z powrotem do tok oraz krótki opis tej podróży. Pełne polecenie i kryteria oceny są w dodatku C.
Na co zwrócić uwagę
- „Konsultacja nie zostaje przerwana” to sygnał zdarzenia nieprzerywającego. „Skanowanie zostaje przerwane” to sygnał zdarzenia przerywającego.
- Oczekiwanie na akceptację z terminem możesz zapisać jako zadanie odbioru (
receive) z przerywającym zdarzeniem granicznym czasowym. Wtedy wiadomość od zamawiającego kierujesz na to zadanie. - Po zdarzeniu granicznym błędu ścieżka może wrócić do wcześniejszego kroku. W tok to zwykły
flowdo identyfikatora tego kroku. - Zanim otworzysz plik w Modelerze, zrób kopię
.tok. Porównanie dwóch plików tekstowych jest najprostszym sposobem, żeby zobaczyć, co naprawdę zmieniłeś.
5.3 Pytania sprawdzające
- Jak zapisać w tok termin 10 dni na zadaniu „Poprawa wniosku”, po którym zadanie zostaje odebrane? Co zmieni dopisanie flagi
noninterrupting? - Dlaczego zdarzenie graniczne błędu nie może mieć flagi
noninterrupting? - Co oznacza błąd
R021w modelu z podprocesem? Jak go poprawić? - Jak w tok połączyć eskalację rzuconą wewnątrz podprocesu ze zdarzeniem granicznym na jego krawędzi?
- Co traci model w podróży tok → BPMN → tok, a co zachowuje? Dlaczego utrata układu diagramu nie jest problemem?