6 Walidacja i zgodność z BPMN
Po spotkaniu: odczytasz komunikat tok check i wskażesz warstwę, z której pochodzi · naprawisz model z wieloma błędami we właściwej kolejności · sprawdzisz zgodność modelu z BPMN 2.0 przez podróż tok → BPMN → tok · Czas: Nauka 40 min, Wyzwanie 50 min
6.1 Nauka
Po co walidacja
Na kursie BPMN skrypt bpmn.py sprawdzał, czy model narysowany w Camunda Modeler przestrzega reguł notacji. W tok sprawdzanie jest częścią codziennej pracy: piszesz kilka wierszy, uruchamiasz tok check, czytasz komunikaty i poprawiasz. Im częściej sprawdzasz, tym mniej błędów nakłada się na siebie.
Walidacja odpowiada na pytanie, czy model jest poprawny: czy da się go przeczytać, czy odwołania prowadzą do istniejących elementów, czy przestrzega reguł BPMN 2.0. Nie odpowiada na pytanie, czy model jest prawdziwy, czyli zgodny z tym, jak naprawdę działa kancelaria albo biblioteka. Do tego potrzebny jest opis procesu i Twoja ocena.
Budowa komunikatu
Każdy komunikat ma ten sam układ:
przyklady/06-kancelaria-z-bledem.tok:23: błąd R001: identyfikator „jednostka” jest już użyty w wierszu 9
└───────────── plik ────────────────┘ └┬┘ └─┬┘ └┬─┘ └───────────────── treść ──────────────────────┘
wiersz │ kod
poziom
- Plik i wiersz mówią, gdzie szukać. W Visual Studio Code kliknij komunikat w terminalu z wciśniętym klawiszem Ctrl (macOS: Cmd), a edytor otworzy plik w tym wierszu.
- Poziom mówi, jak poważny jest problem.
- Kod jest stały. Ten sam błąd ma zawsze ten sam kod, niezależnie od języka komunikatu. Opis wszystkich kodów jest w dodatku B.
- Treść mówi, co jest nie tak. Z opcją
--lang pljest po polsku, bez niej po angielsku.
Na końcu tok check wypisuje podsumowanie: błędy 8, ostrzeżenia 1, uwagi 1.
Trzy poziomy komunikatów
| Poziom | Znaczenie | Co robisz |
|---|---|---|
| błąd | model łamie regułę języka albo notacji; nie powstanie z niego poprawny plik BPMN | poprawiasz zawsze |
| ostrzeżenie | model jest poprawny formalnie, ale prawdopodobnie zawiera pomyłkę | poprawiasz albo świadomie zostawiasz i uzasadniasz |
| uwaga | rada dotycząca stylu albo kompletności | rozważasz |
Polecenia tok bpmn, tok svg i tok export odmawiają pracy, dopóki model ma błędy. Ostrzeżenia i uwagi ich nie zatrzymują.
Warstwy sprawdzania
tok check sprawdza model w kilku warstwach. Pierwsza litera kodu mówi, z której warstwy pochodzi komunikat.
| Litera | Warstwa | Przykład problemu |
|---|---|---|
T |
znaki i wiersze | tabulator we wcięciu (T002), niezamknięty cudzysłów (T001) |
P |
instrukcje | nieznane słowo kluczowe (P001), zły wiersz tabeli decyzyjnej (P009) |
R |
odwołania i struktura | powtórzony identyfikator (R001), odwołanie do nieistniejącego elementu (R002), przepływ komunikatów w jednym basenie (R022) |
C |
model wykonywalny dla Camunda 8 | zadanie skryptowe bez wyrażenia (C040), wyjście z bramki bez warunku (C070) |
D |
tabele decyzyjne | reguły, które mogą pasować jednocześnie (D010) |
F |
wyrażenia FEEL | błąd składni wyrażenia (F002) |
S |
parametry symulacji | niepoprawny rozkład (S001) |
E, W, L |
reguły BPMN 2.0 | przepływ komunikatów z bramki (E009), złączenie innego typu niż rozwidlenie (W051), bramka bez pytania (L020) |
Ostatni wiersz to te same reguły, które znasz ze skryptu bpmn.py z kursu BPMN. tok eksportuje model do BPMN 2.0 i sprawdza go tym samym walidatorem. Dlatego kody E008, W021 czy L020 znaczą w tok dokładnie to samo co w laboratorium z agentem. Komunikaty tej warstwy podają identyfikatory elementów i przepływów, np. f-wolna-rezerwacja. Identyfikator przepływu tok tworzy sam: f- + źródło + cel.
Kolejność warstw i kaskady błędów
Warstwy działają po kolei. Jeśli tekstu nie da się przeczytać (warstwy T i P) albo identyfikatory się powtarzają (R001), dalsze sprawdzanie nie ma sensu. tok zgłasza wtedy tylko te pierwsze błędy. Podobnie reguły BPMN (E, W, L) sprawdza dopiero model bez żadnych błędów.
Zobacz to na przykładzie. Model rejestracji pisma w kancelarii zawiera wiele błędów różnych warstw:
tok 0.1 "Rejestracja pisma w kancelarii" executable
pool uczelnia "Uczelnia" process=rejestracja-pisma
lane kancelaria "Kancelaria"
start wplyw "Pismo wpłynęło" message="Pismo" timer=P1D
user rejestracja "Rejestracja pisma w EZD" form=f-rejestracja
rule dekretacja "Ustalenie jednostki" decision=jednostka result=jednostka
xor pilne "Pismo pilne?"
lane jednostka "Jednostka merytoryczna"
user rozpatrzenie "Rozpatrzenie sprawy" priorytet=wysoki
boundary termin "Minęło 14 dni" timer=P14D
script odpowiedz "Przygotowanie odpowiedzi"
end zalatwiona "Sprawa załatwiona"
pool nadawca "Nadawca"
flow wplyw -> rejestracja -> dekretacja -> pilne
flow pilne -> rozpatrzenie "tak" when="pilnosc = = \"wysoka\""
flow pilne -> rozpatrzeni "nie"
flow rozpatrzenie -> odpowiedz -> zalatwiona
flow termin -> zalatwiona
message zalatwiona -> rejestracja "Odpowiedź"
decision jednostka "Jednostka" hit=unique
| rodzaj: string || jednostka: string |
| "skarga" || "Biuro Rektora" |
| "wniosek" || "Dział Spraw Studenckich" |
Pobierz model z błędami (.tok)
Pierwsze uruchomienie pokazuje jeden błąd:
> tok check przyklady/06-kancelaria-z-bledem.tok --lang pl
przyklady/06-kancelaria-z-bledem.tok:23: błąd R001: identyfikator „jednostka” jest już użyty w wierszu 9
przyklady/06-kancelaria-z-bledem.tok: błędy 1, ostrzeżenia 0, uwagi 0
Tabela decyzyjna nazywa się tak samo jak linia jednostka. Identyfikator musi być unikatowy w całym dokumencie, nie tylko wśród elementów jednego rodzaju. Po zmianie nazwy decyzji na wybor-jednostki (w wierszu 23 i w atrybucie decision= w wierszu 7) tok sprawdza model dalej i wypisuje znacznie więcej:
06-kancelaria-z-bledem.tok:5: błąd R012: zdarzenie może mieć tylko jeden wyzwalacz (message, timer)
06-kancelaria-z-bledem.tok:6: błąd R002: nieznany element (formularz): „f-rejestracja”
06-kancelaria-z-bledem.tok:10: uwaga C011: Zadanie użytkownika „rozpatrzenie” nie ma formularza (form=).
06-kancelaria-z-bledem.tok:10: ostrzeżenie R010: nieznany atrybut „priorytet” w elemencie user
06-kancelaria-z-bledem.tok:11: błąd R032: zdarzenie graniczne „termin” wymaga on=CZYNNOŚĆ
06-kancelaria-z-bledem.tok:12: błąd C040: Zadanie skryptowe „odpowiedz” wymaga expr="…".
06-kancelaria-z-bledem.tok:17: błąd F002: błąd składni FEEL: nieoczekiwany element „=”
06-kancelaria-z-bledem.tok:18: błąd C070: Przepływ pilne -> rozpatrzeni z bramki „pilne” wymaga when="…" albo flagi default.
06-kancelaria-z-bledem.tok:18: błąd R002: nieznany element (element przepływu): „rozpatrzeni”
06-kancelaria-z-bledem.tok:21: błąd R022: przepływ komunikatów zalatwiona -> rejestracja musi łączyć dwa różne baseny
06-kancelaria-z-bledem.tok: błędy 8, ostrzeżenia 1, uwagi 1
To jest kaskada: poprawienie jednego błędu odsłania kolejne. Kaskada działa też w drugą stronę: jeden błąd może wywołać kilka komunikatów. W wierszu 18 literówka w identyfikatorze (rozpatrzeni zamiast rozpatrzenie) daje błąd R002, a brak warunku na tym samym przepływie daje C070. Gdy znikną wszystkie błędy, model trafi do walidatora BPMN, który może zgłosić jeszcze błędy z warstwy E.
Z kaskad wynika prosta strategia naprawy:
- Zaczynaj od pierwszego błędu w kolejności wierszy, a przy kaskadzie od najniższej warstwy (
T,P,R). - Po każdej poprawce uruchom
tok checkponownie. Lista komunikatów może się zmienić bardziej, niż się spodziewasz. - Najpierw błędy, potem ostrzeżenia, na końcu uwagi.
- Czytaj treść, nie tylko kod. Treść zawiera identyfikator elementu i podpowiedź, np.
wymaga on=CZYNNOŚĆ. - Nie usuwaj elementu tylko po to, żeby zniknął komunikat. Jeśli krok procesu istnieje, popraw jego zapis.
Ostrzeżenia i uwagi: dobry styl modelu
Na kursie BPMN poznałeś zasady dobrego modelu: bramka rozgałęziająca ma pytanie, gałęzie mają odpowiedzi, każda ścieżka kończy się nazwanym końcem. W literaturze zbiór takich zasad nazywa się często stylem modelowania. Najbardziej znany jest BPMN Method and Style Bruce’a Silvera. tok sprawdza część tych zasad i zgłasza je jako ostrzeżenia W albo uwagi L. Oto rezerwacja sali w bibliotece zapisana poprawnie formalnie, ale w złym stylu:
xor wolna "Wolny termin"
…
flow wolna -> rezerwacja
flow wolna -> odmowa
styl.tok:5: uwaga L020: „Wolny termin” (wolna): nazwa rozgałęziającej bramki powinna być pytaniem (kończyć się „?”).
styl.tok:11: ostrzeżenie W021: Gałąź f-wolna-rezerwacja bramki „Wolny termin” (wolna) nie ma ani etykiety, ani warunku, ani statusu przepływu domyślnego.
styl.tok:12: ostrzeżenie W021: Gałąź f-wolna-odmowa bramki „Wolny termin” (wolna) nie ma ani etykiety, ani warunku, ani statusu przepływu domyślnego.
styl.tok: błędy 0, ostrzeżenia 2, uwagi 1
Poprawka zajmuje trzy wiersze: xor wolna "Czy termin jest wolny?", flow wolna -> rezerwacja "tak", flow wolna -> odmowa "nie".
Poziomy języka
Opcja --level ogranicza zestaw elementów, które tok check akceptuje. Przydaje się w dwóch sytuacjach: gdy model ma być prostym modelem opisowym dla kierownictwa i gdy pracujesz z agentem AI, który mógłby użyć konstrukcji spoza zakresu zadania.
| Poziom | Akceptuje |
|---|---|
basic |
start i koniec bez wyzwalaczy, zadania ogólne, użytkownika, usługowe i ręczne, bramki xor i and, baseny, linie, komunikaty, dane, adnotacje |
analytic |
całą notację BPMN, bez profilu wykonywalnego, formularzy i tabel decyzyjnych |
full |
wszystko (domyślnie) |
Model kwerendy z terminem 30 dni na poszukiwania jest poprawny na poziomie analytic, ale nie na poziomie basic:
> tok check kwerenda.tok --level basic --lang pl
kwerenda.tok:3: błąd R040: „start” nie jest dostępne na poziomie basic
kwerenda.tok:5: błąd R040: „boundary” nie jest dostępne na poziomie basic
kwerenda.tok: błędy 2, ostrzeżenia 0, uwagi 0
Zdarzenie początkowe jest na tym poziomie dozwolone, ale bez wyzwalacza. Tu ma wyzwalacz wiadomości (message="Wniosek"), dlatego tok zgłasza wiersz 3.
Komunikaty dla programów i agentów
Opcja --json wypisuje te same komunikaty w formacie dla programów:
> tok check przyklady/06-kancelaria-z-bledem.tok --lang pl --json
{
"file": "przyklady/06-kancelaria-z-bledem.tok",
"errors": 1,
"diagnostics": [
{
"code": "R001",
"severity": "error",
"line": 23,
"id": "jednostka",
"message": "identyfikator „jednostka” jest już użyty w wierszu 9"
}
]
}
Z tego formatu korzysta agent AI na spotkaniu 9. Agent nie musi zgadywać, co znaczy komunikat. Dostaje kod, wiersz i identyfikator elementu, poprawia jeden wiersz i sprawdza model ponownie.
Forma kanoniczna
Poprawny model można zapisać na wiele sposobów: z różnymi wcięciami, w innej kolejności atrybutów, z łańcuchami przepływów albo bez nich. Polecenie tok fmt -w zapisuje go w jednej, ustalonej formie kanonicznej (spotkanie 2). tok fmt --check tylko sprawdza, czy plik już jest w tej formie.
Forma kanoniczna jest miarą porządku, nie poprawności. Ma jednak praktyczne znaczenie: dwa modele w formie kanonicznej różnią się tylko tam, gdzie różnią się treścią. Dlatego przed oddaniem zadania i przed zapisaniem zmian w repozytorium zawsze uruchamiasz tok fmt -w.
Zgodność z BPMN: podróż w obie strony
Jak sprawdzić, że tok naprawdę jest zapisem BPMN, a nie innym językiem, który tylko podobnie wygląda? Służy do tego podróż w obie strony (round trip):
model.tok ──tok bpmn──► model.bpmn ──tok import──► model2.tok ──tok bpmn──► model2.bpmn
Jeśli model.bpmn i model2.bpmn opisują te same elementy z tymi samymi powiązaniami, przekład nie zgubił ani nie dodał żadnej informacji. Ten test jest częścią zestawu testów narzędzia tok. Przechodzą go m.in. wszystkie diagramy z kursu BPMN.
Podróż działa także w drugą stronę. tok import zamienia na tok plik narysowany w Camunda Modeler. Oto pierwszy model z kursu BPMN, wypożyczenie międzybiblioteczne, zaimportowany poleceniem tok import 01-wypozyczenie-pierwszy-model.bpmn --no-flow-ids:
tok 0.1 "Wypożyczenie międzybiblioteczne" id=Definitions_Wypozyczenie namespace=https://codeberg.org/MarekDeja/ipm/diagramy/01 collaboration=Collaboration_Wypozyczenie
pool Participant_Biblioteka "Biblioteka uczelniana" process=Process_Wypozyczenie
lane Lane_Czytelnik "Czytelnik"
start Start "Potrzeba książki"
user Task_Zlozenie "Złożenie zamówienia"
lane Lane_Bibliotekarz "Bibliotekarz"
user Task_Sprawdzenie "Sprawdzenie katalogów"
xor Gw_Dostepna "Czy książka dostępna lokalnie?"
user Task_Wskazanie "Wskazanie egzemplarza"
user Task_Zamowienie "Zamówienie w innej bibliotece"
end End_Wskazany "Egzemplarz wskazany"
end End_Zamowione "Zamówienie złożone"
flow Start -> Task_Zlozenie -> Task_Sprawdzenie -> Gw_Dostepna
flow Gw_Dostepna -> Task_Wskazanie "tak"
flow Gw_Dostepna -> Task_Zamowienie "nie"
flow Task_Wskazanie -> End_Wskazany
flow Task_Zamowienie -> End_Zamowione
Import zachowuje identyfikatory z pliku, bo pod nimi model może być już znany w innych systemach. Dlatego nazywają się Task_Zlozenie albo Gw_Dostepna, a w nagłówku są dodatkowe atrybuty (id=, namespace=, collaboration=). Opcja --no-flow-ids pomija identyfikatory przepływów, żeby tok mógł zapisać je jako łańcuchy. Elementy, których tok 0.1 nie obsługuje (np. bramka złożona), import pomija i wypisuje ostrzeżenie.
Import przydaje się, gdy instytucja ma już modele narysowane w edytorze graficznym i chce je przenieść do repozytorium tekstowego albo przekazać agentowi AI do analizy.
6.2 Wyzwanie
Polecenie: napraw dwa modele z błędami. Zapisuj, w jakiej kolejności poprawiałeś komunikaty.
Dane wejściowe:
- Model rejestracji pisma
06-kancelaria-z-bledem.tokz części Nauka. Proces: pismo przychodzi od nadawcy, kancelaria rejestruje je w EZD (formularz z rodzajem pisma), system ustala jednostkę według tabeli decyzyjnej. Pisma pilne trafiają do jednostki od razu, a pozostałe kancelaria najpierw skanuje razem z załącznikami do EZD. Jednostka ma 14 dni na rozpatrzenie; po tym czasie sprawa zostaje zamknięta jako przeterminowana. W terminie jednostka przygotowuje odpowiedź i wysyła ją nadawcy. - Model recenzji wydawniczej
06-wydawnictwo-z-bledem.tok, poniżej. Proces: redakcja ocenia maszynopis, przyjęty wysyła równolegle dwóm recenzentom (basen „Recenzenci”), po zebraniu obu recenzji system ustala decyzję według tabeli, a rada wydawnicza zatwierdza plan wydawniczy.
tok 0.1 "Recenzja wydawnicza"
pool wydawnictwo "Wydawnictwo uczelniane"
lane redakcja "Redakcja"
start wplynal "Maszynopis wpłynął"
usr ocena "Ocena wstępna maszynopisu"
xor przyjety "Czy maszynopis przyjęty do recenzji?"
and recenzje "Wysłanie do recenzentów"
xor zebrane "Recenzje zebrane"
rule decyzja "Decyzja o publikacji" decision=publikacja
end wydany "Skierowano do druku"
end odrzucony "Maszynopis odrzucony"
lane rada "Rada wydawnicza"
user zatwierdzenie "Zatwierdzenie planu"
pool recenzent "Recenzenci"
flow wplynal -> ocena -> przyjety
flow przyjety -> recenzje -> zebrane "tak"
flow przyjety -> odrzucony "nie"
flow recenzje -> zebrane
flow zebrane -> decyzja -> zatwierdzenie -> wydany
message recenzje -> recenzent "Maszynopis do recenzji"
decision publikacja "Publikacja" hit=first
| recenzja1: string | recenzja2: string || decyzja: string |
| "pozytywna" | "pozytywna" || "druk" |
| "negatywna" | "negatywna" |
| - | - || "trzecia recenzja" |
Pobierz model z błędami (.tok)
Kroki:
- Uruchom
tok check --lang pli zapisz liczbę błędów, ostrzeżeń i uwag. - Popraw pierwszy błąd i uruchom sprawdzenie ponownie. Powtarzaj, aż nie będzie błędów. Ostrzeżenia popraw albo uzasadnij.
- Dla każdej poprawki zapisz w pliku
naprawa-06.md: kod komunikatu, warstwę, wiersz i co zmieniłeś. Zaznacz komunikaty, które pojawiły się dopiero po wcześniejszej poprawce (kaskada). - Uruchom
tok fmt -w,tok bpmni otwórz modele w Camunda Modeler. - Wykonaj podróż w obie strony dla jednego modelu:
tok bpmn,tok importwyniku do nowego pliku,tok fmt -wi porównaj oba pliki.tok. Zapisz, czym się różnią i dlaczego.
Rezultat: poprawione pliki kancelaria.tok i wydawnictwo.tok (0 błędów, forma kanoniczna) oraz naprawa-06.md. Nie oddajesz ich na Pegazie.
Praca: w parach; jedna osoba poprawia, druga prowadzi dziennik w naprawa-06.md. Przy drugim modelu zamieniacie się rolami.
Czas: 50 minut.
Na co zwrócić uwagę
- Numery wierszy w komunikatach odnoszą się do pliku po Twoich zmianach. Po dopisaniu wiersza w środku pliku kolejne komunikaty przesuwają się w dół.
R002z literówką w identyfikatorze poprawiasz w miejscu odwołania, nie w deklaracji. Sprawdź, który zapis jest właściwy.- Model recenzji zawiera bramkę równoległą. Pamiętaj z kursu BPMN: rozwidlenie AND łączysz bramką AND (
W051). - Przepływ komunikatów nie może wychodzić z bramki (
E009). Wiadomość do innego basenu wysyła zadanie wysyłania albo zdarzenie. - Po podróży tok → BPMN → tok identyfikatory przepływów mogą pojawić się jako
id=w wierszachflow. To nie błąd. Opcja--no-flow-idswtok importdaje zapis bliższy oryginałowi.
6.3 Pytania sprawdzające
- Z jakich części składa się komunikat
tok check? Która z nich nie zmienia się po przełączeniu języka komunikatów? - Czym różni się błąd od ostrzeżenia? Które polecenia
tokodmawiają pracy przy błędach? - Dlaczego po poprawieniu jednego błędu liczba komunikatów może wzrosnąć? Podaj przykład kaskady z modelu kancelarii.
- Do czego służy opcja
--level basic? Podaj sytuację, w której warto jej użyć. - Co sprawdza podróż tok → BPMN → tok i dlaczego świadczy o zgodności języka z BPMN 2.0?