O UML 2.0, czyli co nowego w projektowaniu. Część 3.

Sebastian Wyrwał
wyrwal@firma-informatyczna.com

 

W poprzednim odcinku poza prostym, praktycznym przykładem dotyczącym przypadków użycia, rozpoczęto omawianie diagramów aktywności. Pokazano proste i złożone czynności, węzły decyzyjne oraz modelowanie współbieżności. Notacja związana z diagramami aktywności jest dość rozbudowana i obfituje w różne środki przekazu. Wynika to zapewne z tego, iż diagramy te mają bardzo szerokie zastosowania – od zapisu algorytmów związanych z przetwarzaniem danych, aż po modelowanie procesów biznesowych w przedsiębiorstwie. Stopień szczegółowości tych diagramów może być bardzo różny: można pokazywać pewien proces biznesowy (np. w bankowości) bardzo ogólnie, można również pokazywać go bardzo dokładnie, z uwzględnieniem wszystkich dokumentów i danych, które są potrzebne przy rozpatrywaniu wniosku o kredyt. Warto zauważyć, iż grupa odbiorców tych diagramów jest dość szeroka.

Innym powodem skomplikowania diagramów aktywności są zmiany formalne. Ten sam symbol graficzny może w językach w wersji 1.5 i 2.0 oznaczać formalnie zupełnie inny element modelu, który jednak w praktyce może być stosowany w tych samych lub podobnych okolicznościach. Z tych różnic wiele osób, które korzystają z języka UML, nie zdaje sobie nawet sprawy. Różnice te mogą jednak mieć dość daleko idące konsekwencje. Trudno jednoznacznie odpowiedzieć na pytanie, czy takie zmiany w samym języku UML są korzystne. Poprawny diagram aktywności powinien mieć dokładnie to samo znaczenie w wersji 1.5, jak i wersji 2.0. W wersji 1.3 UML diagramy aktywności były bardzo podobne do diagramów stanów, obecnie maszyny stanowe różnią się znacznie od aktywności.

Problemy tego rodzaju mogą być szczególnie istotne dla twórców narzędzi do modelowania. Z drugiej jednak strony, trudno wymagać od przeciętnego użytkownika języka, aby bardzo dogłębnie analizował nową wersję specyfikacji (przede wszystkim dokument [2]) i porównywał ją z wersjami poprzednimi. Zajęcie to lepiej chyba pozostawić specjalistom, choć w założeniu dokument [2] przeznaczony jest dla użytkowników języka. Niektóre pozycje [4] zalecają stosowanie wyłącznie podstawowych konstrukcji języka. Trudno byłoby się z nimi nie zgodzić, gdyby nie to, że definicja pewnych „istniejących od dawna w UML-u bytów” również podlega zmianom. Ponadto niechęć do uczenia się nowych rzeczy jest nierozwojowa i przypomina do pewnego stopnia znaną kiedyś niechęć do paradygmatu obiektowego. Czytając tytuł pozycji [4] można dojść do wniosku, iż jest on bardzo mylący, gdyż książka ta właściwie nie porusza zagadnień związanych z językiem w wersji 2.0. Idąc dalej można dojść do wniosku, iż książka ta pokaże jak stosować w praktyce „nowości” wprowadzone w języku UML. Niestety, już pobieżna lektura pokazuje, że – zdaniem autorów – języka w wersji 2.0 nie trzeba wcale używać. Z książki można się dowiedzieć, iż jej autorzy zajmują się głównie prowadzeniem szkoleń. Prezentowane przez nich podejście jest więc zapewne dla nich samych bardzo wygodne, bo nie muszą się uczyć nowych rzeczy. Warto jeszcze zauważyć, że prezentowane w książce przykłady są typowo akademickie i z praktyką nie mają w zasadzie nic wspólnego – wbrew temu, co mówi drugie zdanie tytułu.

Oczywiście autor niniejszej publikacji nie twierdzi, iż należy od razu i koniecznie stosować wszystkie nowe byty. Należy jednak zdawać sobie sprawę z ich istnienia, a stosować je wtedy, gdy ich użycie jest uzasadnione. Oczywiście ucząc innych języka UML, lepiej rozpocząć od opanowania podstaw, w miarę potrzeby przechodząc do zagadnień bardziej zaawansowanych. Uczenie języka UML, powinno być chyba podobne do uczenia matematyki, które opiera się na ćwiczeniach. Czytanie samej teorii chyba nie nauczyło nikogo rozwiązywania zadań. Ironią jest to, że na studiach matematycznych uczy się dowodów twierdzeń. A że niektóre są trudne, to (podobno) studenci opanowują je pamięciowo. Samo przeczytanie książki z pewnością nie wystarczy, aby nauczyć się projektować. Z nauką programowania jest chyba o wiele łatwiej, ponieważ w przypadku prościutkich programów ich poprawność w pewnym stopniu weryfikuje kompilacja i wykonanie. W przypadku użycia języka UML sprawa wygląda znacznie gorzej, gdyż można w ogóle nie zdawać sobie sprawy z własnych, oczywistych dla osoby znającej język UML, błędów.

Kontynuując rozważania dotyczące użycia języka UML należy podkreślić, iż dokument [2] mało mówi o zastosowaniu języka UML w praktycznym projekcie. Jest on, jak powiedziano w pierwszym odcinku, obszerny – jednak jego opanowanie ze zrozumieniem może uczynić z kogoś eksperta od języka UML, nie uczyni jednak z nikogo projektanta. Aby nim być trzeba znać np. UML, metodykę ale przede wszystkim trzeba mieć umiejętności i doświadczenie.

O diagramach aktywności i ich zastosowaniu

Rozwijanie prostych diagramów aktywności – np. takich, jak pokazane w poprzednim odcinku, może wymagać ich uszczegóławiania i grupowania poprzez nadanie pewnej organizacji.

Praktyczne modelowanie procesów biznesowych może wymagać ukazania większej ilości szczegółów – np. związanych z danymi, które są potrzebne w różnych aktywnościach. Ważnym mechanizmem jest też grupowanie aktywności przy użyciu partycji (torów). Pozwala ono na pokazanie, kto (co) i gdzie wykonuje daną czynność. Pozwala to na ukazanie współpracy np. różnych działów organizacji lub współpracy organizacji z firmami zewnętrznymi. Użycie konstrukcji regionu rozszerzenia pozwala na dość łatwe modelowanie złożonych algorytmów i pokazanie przetwarzania danych w ogóle.

Ponieważ odcinek ten traktuje o aktywnościach, warto bardziej dokładnie przedstawić, do czego mogą być one użyte.

 

Tabela 1. Zakres użycia aktywności

Kategorie osób Do czego mogą być użyte
Specyfikacja PU Analitycy, specjaliści dziedzinowi
Specyfikacja procesów biznesowych Analitycy, specjaliści dziedzinowi
Specyfikacja algorytmów Projektanci, deweloperzy
Specyfikacja przepływów czynności na potrzeby metodyki Projektanci metodyki, osoby korzy stające z metodyk, zarządzający projektem
Dokumentowanie metod Programiści, testerzy
Projektowanie systemów rozproszonych Projektanci systemów rozproszonych

Najwięcej mówi się o dwóch pierwszych zastosowaniach, ale trzeba mieć świadomość pozostałych zastosowań, które mogą również obejmować zastosowania Sieci Petriego, w stronę których diagramy aktywności ewoluują. Opisanie złożonych algorytmów może być dość zwięzłe dzięki wprowadzonym w wersji 2.0 udogodnieniom – takim, jak np. obszar rozszerzenia. Warto podkreślić, iż diagramy aktywności są stosowane wtedy, gdy najistotniejsze jest określenie „co ma być zrobione”, z pominięciem określenia realizatora czynności. Użycie diagramów aktywności do opisywania przypadków użycia jest dość zrozumiałe, gdy weźmie się pod uwagę, iż wewnętrzna struktura systemu nie jest jeszcze znana. Wydaje się również, że opisanie algorytmu na poziomie koncepcji nie wymaga dokładnego określenia realizatora czynności. Należy zasygnalizować, iż diagramy aktywności są mocniejszym narzędziem niż diagramy sekwencji.

Uszczegóławianie diagramów aktywności

Dalsze uszczegóławianie diagramów aktywności może odbywać się poprzez:

(i) wykorzystanie akcji,
(ii) coraz to bardziej dokładne modelowanie przepływów danych, obsługi wyjątków, wprowadzanie partycji (torów) etc.

Jeśli przedmiotem naszego zainteresowania będzie opisywanie przypadków użycia, modelowanie procesów biznesowych, czy specyfikowanie algorytmów, to znacznie bardziej istotny będzie drugi sposób postępowania. Jeśli, z naszego punktu widzenia, bardziej istotne będzie tworzenie wykonywalnych modeli, transformacja modeli, lub pokazanie sposobu realizacji w konkretnym środowisku wykonawczym, to bardziej istotny będzie sposób pierwszy. Oczywiście oba sposoby nie wykluczają się wzajemnie.

Przed przejściem do dalszych rozważań, warto uporządkować pojęcia związane z diagramami aktywności. Podstawowe składowe diagramów aktywności to:

  • Aktywności;
  • Obiekty (w tym stereotypowanie: bufory i magazyny danych, które są nowością w UML-u 2.0);
  • Krawędzie (Zmiany formalne);
    – Przepływ sterowania,
    – Przepływ obiektów,
    – Krawędź wyjątku,
  • Węzły sterowania (Zmiany formalne);
    – Rozwidlenie (ForkNode),
    – Scalenie (JoinNode),
    – Złączenie (MergeNode),
    – Decyzja (DecisionNode),
    – Węzły końcowe (FinalNode),
    · Zakończenie Aktywności (ActivityFinalNode),
    · Zakończenie Przepływu (FlowFinalNode),
  • Węzeł początkowy.

Aktywności – jak już powiedziano w poprzednim odcinku – mogą być proste lub złożone. Krawędzie zastępują przejścia między stanami, które były wykorzystywane do wersji 1.5 języka UML włącznie. Pomiędzy aktywnościami mogą przepływać obiekty. Generalnie obiekty na diagramach aktywności nie mogą być łączone ze sobą. Wyjątkiem od tej zasady jest przepływ do buforu lub magazynu. Węzły sterowania „regulują pracę” diagramu aktywności. Formalnie ich działanie dotyczy tokenów (żetonów). Wykonanie aktywności rozpoczyna się od węzła początkowego, a kończy na węźle Zakończenia Aktywności (ActivityFinalNode). Osiągnięcie tego węzła przez jakikolwiek token kończy wszystkie przepływy. Osiągnięcie przez token węzła Zakończenia Przepływu kończy bieżący przepływ, ale nie niszczy innych przepływów w obrębie danego diagramu. W praktyce węzły Zakończenia Przepływu są używane np. przy modelowaniu pętli lub rekurencji. Rozwidlenie i scalenie są stosowane przy modelowaniu współbieżności, a złączenie i decyzja przy modelowaniu alternatywnych przepływów (decyzji). Notacja graficzna dla rozwidlenia i scalenia to „gruba kreska” a dla złączenia i decyzji to romb. Przykłady zostały zaprezentowane w poprzednim odcinku.

Przedstawiony repertuar środków wystarczy do „zgrubnego” opisania przypadków użycia i procesów biznesowych oraz przepływów czynności w metodyce. Jest on jednak niewystarczający, gdy trzeba przy pomocy notacji diagramów aktywności określić w zwięzły sposób, jakie dokumenty są potrzebne np. przy rozpatrywaniu wniosku kredytowego. Trudno również zwięźle zapisać złożony algorytm obliczający FFT (Szybka Transformata Fouriera).

Poza przedstawionymi już elementami modelu, język UML oferuje bogaty arsenał środków, które mogą ułatwić tworzenie różnych diagramów aktywności. Można do nich zaliczyć:

  • Partycje (rozbudowane w UML 2.0; partycje mogą być hierarchiczne i wielowymiarowe);
  • Parametry (ActivityParameterNode) i zbiory parametrów (ParameterSet) (oba nowe w UML 2.0);
  • Obsługa wyjątków (zmieniona w stosunku do UML 1.5);
    – węzeł chroniony,
    – węzeł obsługujący,
    – krawędź wyjątku,
    – typ wyjątku,
    – wejście wyjątku (obiekt),
  • Regiony (nowe w UML 2.0);
    – region wystąpienia wyjątku (InteruptableActivityRegion),
    – region rozszerzenia (ExpansionRegion),
  • Konektor;
  • Wagi.

Partycje są elementem grupującym. Pozwalają one określić gdzie i przez co (kogo) dana aktywność jest wykonywana. Parametr jest obiektem i odpowiada wejściu lub wyjściu. Zbiory parametrów pozwalają na zapisanie alternatywnych zestawów parametrów, z których w danym wykonaniu może być wybrany po jednym dla wejścia i wyjścia.

Obsługa wyjątków przypomina tę znaną z języków programowania. Sytuacja wyjątkowa może wystąpić w węźle chronionym. Wyjątek jest przekazywany do krawędzi wyjątku i obsługiwany w węźle obsługującym. Region rozszerzania pozwala na połączenie notacji dla całej serii danych (na zewnątrz regionu) z notacją dla pojedynczych danych (wewnątrz regionu). Można określić sposób wykonania „zawartości regionu” jako równoległy, iteracyjny lub strumieniowy. Region wystąpienia wyjątku jest rodzajem grupy aktywności. Konektor pozwala na przerwanie krawędzi i wznowienie jej w innym miejscu. Ułatwia to notację. Wagi pozwalają na określenie, ile żetonów jest potrzebnych, aby akcja została zapoczątkowana.

W wersji 2.0 języka UML wprowadzono również pojęcie Aktywności Złożonej (StructuredActivityNode). Stanowi ona mechanizm grupujący i może być definiowana przez grupy aktywności (czyli w praktyce na osobnym diagramie). Szczególnym rodzajem aktywności złożonych są:

  • Węzeł warunkowy (ConditionalNode);
  • Węzeł pętli (LoopNode).

Specyfikacja nie określa, jak używać tych węzłów. Notacja dla obu powyższych węzłów jest prosta – są to aktywności złożone, odpowiednio ze stereotypami <<conditional>> oraz <<loop>>. Ich użycie może w znaczący sposób ułatwić zapisanie pętli i instrukcji warunkowych.

Prawidłowe użycie aktywności złożonej ze stereotypem <<loop>> wymaga określenia:

  • części inicjującej (setupPart) będącej zbiorem węzłów i krawędzi, które inicjują pętlę,
  • części będącej ciałem pętli (bodyPart),
  • testu (test), który wylicza wartość logiczną określającą, czy wykonanie pętli ma być kontynuowane,
  • decyzji (decider), która określa, czy ciało ma być wykonane.

Wydaje się, że części te mogą być określone poprzez podział aktywności złożonej na partycje.

Bardziej skomplikowane wydaje się użycie aktywności złożonej ze stereotypem <<conditional>>, które wymaga zdefiniowania klauzul (co najmniej jednej). Klauzula to warunek i ciało, które jest wykonywane, gdy warunek jest spełniony. Specyfikacja nie określa jak zapisywać owe warunki i ciała. Być może podział aktywności na partycje jest właściwym pomysłem.

Przykłady

Na rysunku 1 przedstawiono aktywność PrzyjęcieNaParking. Ma ona dwa parametry wejściowe: NrRejestracyjny i CzasWjazdu oraz jeden parametr wyjściowy: Pokwitowanie.

 


Rys. 1. Wykorzystanie parametrów aktywności

 

Na rysunku 2 pokazano zastosowanie partycji dwuwymiarowych z podpartycjami. Przedstawiono proces biznesowy parkowania samochodu na „eleganckim” parkingu, na którym sama czynność parkowania wykonywana jest przez pracownika parkingu. Właściciel auta (kierowca) wjeżdża na parking. Pracownik parkingu siedzący w budce, która znajduje się przy wjeździe na parking przyjmuje pojazd na parking. Inny pracownik parkuje pojazd na parkingu. Pionowy podział na partycje wprowadza dwie lokalizacje wykonywania czynności: wjazd na parking (przy budce) oraz miejsca parkowania. Podział poziomy wyróżnia role Kierowcy oraz Pracownika, przy czym na prezentowanym parkingu istnieją dwa rodzaje pracowników: Pracownik w Kiosku oraz Pracownik Parkujący. Ten ostatni podział realizowany jest poprzez zastosowanie podpartycji.


Rys. 2.
Partycje

Na rysunku 3 przedstawiono obsługę wyjątków. Wykonanie czynności WyjazdZParkingu, może zostać przerwane na skutek uszkodzenia szlabanu. Krawędź wyjątku zapisywana jest w sposób przypominający symbol wyładowywania elektrycznego. Sam wyjątek zapisywany jest przy pomocy węzła obiektowego.


Rys. 3.
Obsługa wyjątków

Na rysunku 4 przedstawiono zastosowanie regionu rozszerzenia. Zakładając, iż opłata na parkingu naliczana jest za każdą rozpoczętą godzinę zegarową (czyli np. o 12, 13, 14, etc.) diagram prezentowany na rysunku 4 pokazuje, iż doliczenie opłaty za następną godzinę parkowania wykonywane jest dla wszystkich samochodów. Na zewnątrz obszaru rozszerzenia znajdują się zbiorowości samochodów, ale wewnątrz tego obszaru wykonanie aktywności pokazane jest dla jednego samochodu.


Rys. 4.
Użycie regionu rozszerzenia.

Na rysunku 5 przedstawiono użycie regionu wystąpienia wyjątku. Odebranie sygnału OdrzuceniePłatności powoduje zatrzymanie przepływów w obrębie regionu i przejście do węzła obsługującego (AnulowanieZakupu).


Rys. 5.
Użycie regionu wystąpienia wyjątku

Na rysunku 6 przedstawiono użycie wag. Każde zamówienie jest przekazywane do składnicy zamówień. Gdy uzbiera się 10 zamówień, są one przekazywane do realizacji.


Rys. 6.
Użycie wag

Diagramy aktywności są dość skomplikowane. Wynika to z faktu, iż ich zastosowanie jest bardzo szerokie. W wersji 2.0 języka UML dokonano dość istotnych zmian w porównaniu z wersjami poprzednimi. Nowe elementy dostarczają dość silnych mechanizmów i warto ich używać, gdy może się to przyczynić do bardziej zwięzłego lub dokładnego zapisu.

Literatura

[1]. Unified Modeling Language: Infrastructure version 2.0. www.omg.org, Marzec 2006
[2]. Unified Modeling Language: Superstructure version 2.0. www.omg.org, Sierpnień 2005
[3] The Rational Unified Process – an Introduction Second Edition, Phillippe Kruchten, Addison-Wesley 2000
[4] UML 2.0 w akcji. Przewodnik oparty na projektach, P. Graessle, H. Baumann, P. Baumann

c.d.n.