Diagram aktywności

Diagram przypadków użycia (omówiony w e‑materiale Programowanie obiektowe – projekt, etap IP1HNnJQz9Programowanie obiektowe – projekt, etap I) umożliwia odczytanie, co dany użytkownik może zrobić. Natomiast diagram aktywności pokazuje, jak można to osiągnąć.

Przeanalizujmy diagram obrazujący czynność wsiadania kierowcy do samochodu.

R1eDzxrE7nJXi
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Diagram przedstawia kolejne kroki omawianej czynności. Zwróćmy uwagę, że:

  • czarna kropka oznacza początek aktywności (stosujemy tylko jedno takie oznaczenie),

  • strzałki wyznaczają następstwo akcji,

  • grot strzałki wskazuje kierunek, zgodnie z którym należy odczytywać diagram,

  • ramka z zaokrąglonymi rogami oznacza czynność lub akcję, którą należy w danym momencie wykonać,

  • akcja to pojedyncza, atomowa i niepodzielna operacja,

  • czynność to grupa zagregowanych akcji,

  • czarna kropka z pierścieniem oznacza koniec czynności.

R8eGKsQHNjwXd
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Czynność otwarcia drzwi składa się zatem z czterech, wykonywanych kolejno pojedynczych akcji.

W diagramie aktywności możemy stosować również bloczek rozgałęzienia, który ma postać deltoidu:

R1bP8Nz4hmRiL
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Bloczek ten pozwala sterować przebiegiem aktywności w zależności od stanu systemu. Domyślnie ma dwa wyjścia i zachowuje się podobnie jak operator warunkowy if‑else. Obydwa wyjścia oznaczają sytuacje przeciwne, jak w przedstawionym przykładzie – zamek w drzwiach może być albo otwarty, albo zamknięty i domyślnie nie ma trzeciego możliwego rozwiązania. Jeżeli jest zamknięty, przechodzimy do akcji wyjęcia kluczy z kieszeni, a jeżeli otwarty, przechodzimy bezpośrednio do akcji otwarcia drzwi.

Diagram aktywności przypomina programowanie. Obrazuje czynności, jakie muszą wystąpić po kolei w danym systemie, abyśmy mogli otrzymać końcowy wynik, który będzie zgodny z naszymi oczekiwaniami.

Za pomocą deltoidu oznaczamy również złączenie. Na przedstawionym przykładzie widzimy rozgałęzienie z wyborem środka lokomocji. W pierwszym przypadku akcja to Jazda autobusem, w drugim – Jazda samochodem. Po zakończeniu każdej z tych akcji strzałki łączą się w bloku złączenia, co oznacza, że dalszy ciąg podróży do szkoły będzie przebiegać tak samo w obu przypadkach.

RMTasXzAGsfW3
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Należy doprecyzować, że bloczek złączenia inicjuje dalsze działanie za każdym razem, gdy dotrze do niego sterowanie, nie czekając na sterowanie ze wszystkich węzłówwęzeł sterowaniawęzłów. Nie można więc za jego pomocą budować zależności współbieżnych.

Ważne!

Współbieżność to sytuacja, gdy akcje lub czynności dzieją się jednocześnie.

Rozwidlenie (fork), podobnie jak scalenie (join), oznaczamy za pomocą długiej kreski.

Współbieżność nie definiuje nam kolejności wykonywania działań, a jedynie informuje, że dzieją się one w tym samym czasie. Ponieważ nie ma znaczenia, w jakiej kolejności zostaną wykonane, nie powinny być od siebie zależne. Przyjrzyjmy się temu na przykładzie innej sytuacji:

Rz7A7KtkeGTEH
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

W przedstawionym przykładzie po rozpoczęciu czynności powstają dwa ciągi akcji. Pierwszy składa się z jednej akcji (Wyjęcie makaronu z szafki), a drugi z dwóch (Wstawienie wody oraz Posolenie wody). Oba mogą być wykonywane niezależnie i nawet jednocześnie, bo nieistotne jest, czy najpierw wyjmiemy z szafki makaron, czy wstawimy wodę na kuchenkę. Natomiast akcja wsypania makaronu do wody rozpocznie się dopiero wtedy, gdy wszystkie wcześniejsze akcje zostaną zakończone. Ważne jest jedynie, że odbywają się one w tym samym momencie.

Dla zainteresowanych

W pierwszych komputerach procesy nie mogły być współbieżne, a akcje wykonywały się po kolei. We współczesnych procesorach czynności dzieją się – z punktu widzenia użytkownika – jednocześnie. Dzięki temu może działać więcej niż jeden program. W tym samym czasie możemy mieć uruchomioną grę, przeglądarkę, odtwarzacz muzyki oraz setki procesów, które rywalizują o zasoby naszego procesora. Jednowątkowe i jednordzeniowe procesory wykonują de facto jedną operację na raz. Oznacza to, że aby mogły jednocześnie działać różne programy, czas pracy procesora musi być dzielony pomiędzy nie. Każdy proces otrzymuje do dyspozycji określony czas, w jakim jest realizowany, po czym procesor zaczyna obsługę kolejnego procesu. Oczywiście im więcej uruchomionych procesów, tym większe obciążenie procesora, a co za tym idzie – wolniejsze wykonywanie programów. Procesory wielowątkowe i wielordzeniowe potrafią natomiast realizować wiele procesów w tym samym czasie, bez konieczności przełączania się pomiędzy nimi. Każdy proces realizowany jest w oddzielnym wątku. Obecnie najpopularniejsze są procesory dwu- i czterordzeniowe. Oznacza to, że procesor zbudowany jest z dwóch fizycznych rdzeni (mówiąc w dużym uproszczeniu: z dwóch oddzielnych procesorów, połączonych jednak w jeden układ). Dodatkowo każdy rdzeń, dzięki wykorzystaniu techniki wielowątkowości (ang. multithreading) potrafi obsługiwać jednocześnie wiele wątków. Dzięki temu np. procesor czterordzeniowy może realizować aż osiem wątków w tym samym czasie – ma więc ośmiokrotnie większą wydajność niż identyczny procesor jednordzeniowy z jednym wątkiem. Jeśli chcesz samodzielnie zgłębić temat budowy procesora, sięgnij do odpowiedniej literatury, np. Organizacja i architektura systemu komputerowego Williama Stallingsa.

W diagramie aktywności istnieje również możliwość przenoszenia obiektów pomiędzy czynnościami.

RxpqDwoCbngjU
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

W diagramie wybraliśmy obiekt (Makaron), a następnie przekazaliśmy go do kolejnej czynności, jaką jest Ugotowanie makaronu. Zakładamy, że Wybór makaronu ma wpływ na końcowy wynik całej czynności.

Kolejnymi elementami diagramu są konektory, czyli małe okrągłe bloczki, umożliwiające łączenie oddalonych od siebie obiektów. Konektory są uzupełniającymi składnikami diagramu aktywności, poprawiającymi jego czytelność.

Można powiedzieć, że konektory to swego rodzaju „portale” dla sterowania.

R14nNQUW5GGaR
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

W diagramie aktywności można uwzględnić jeszcze sygnały oraz tory pływackie (swimlines). Te pierwsze (przedstawiane jako przerywane linie ze strzałkami) obrazują przesyłanie informacji pomiędzy różnymi wykonawcami danej czynności. Tory pływackie (w postaci ramek) pokazują, które z czynności przypisane są danemu wykonawcy.

R1QKZ1Fk6YCKb
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

W przestawionym przykładzie tory pływackie to okienka oznaczone jako Program 1Program 2. Bloczki w okienku Program 1 wykonywane są przez Program 1, a bloczki w Program 2 wykonywane są przez Program 2. Tory pływackie mogą mieć fragmenty wspólne – jeśli tor nazwiemy: Program 1, Program 2, oznaczać to będzie, że daną akcję lub czynność mogą wykonać obydwa programy. Program 1 oraz Program 2 możemy nazywać aktorami.

Bloczek z napisem Uruchom program służy do przesyłania sygnału, który może mieć więcej niż jedno wyjście. W przykładzie stworzyliśmy nowy węzeł sterowania. Oznacza to, że obie czynności wykonywane są asynchronicznie – w przeciwieństwie do opisanej wcześniej współbieżności, która wykonuje się synchronicznie. Przerywana strzałka oznacza, że wysyłany jest sygnał, a nie, że węzeł sterowaniawęzeł sterowaniawęzeł sterowania przechodzi w prawo.

Okrąg ze znakiem X oznacza zakończenie węzła sterowania. Należy pamiętać, że każdy węzeł musi się gdzieś kończyć – w przeciwnym razie będzie on sformułowany niepoprawnie. Węzeł może zakończyć się czynnością lub właśnie takim „martwym punktem”.

Diagram pakietów

Przyjrzyjmy się diagramowi pakietów. Składa się on z pakietów, których elementami mogą być między innymi:

  • inne pakiety,

  • klasyklasaklasy.

Istnieje wiele innych elementów, które mogą się w diagramie pakietów znaleźć, jednak wymienione dwa są najistotniejsze.

W klasach wpisanych w diagram pakietu nie definiujemy metod. Jest to spowodowane faktem, że do definiowania klas wykorzystujemy diagram klas, który stworzymy na podstawie diagramu pakietów.

Istnieje kilka różnych, równoważnych notacji tych diagramów, jednak omówimy tylko jedną konwencję.

Dla zainteresowanych

Jeśli chcesz poznać inne notacje, poszukaj w internecie informacji o diagramach pakietów. Rzetelne materiały na ten temat można znaleźć na stronach uczelni wyższych oferujących kierunki informatyczne, ponieważ prowadzi się tam przedmioty związane z projektowaniem oprogramowania. Bardzo dobre omówienia diagramów (wraz z przykładami) znajdziesz między innymi na stronach Akademii Górniczo‑Hutniczej czy Polsko‑Japońskiej Akademii Technik Komputerowych.

Diagram pakietów charakteryzuje wyraźne oddzielenie od siebie poszczególnych komponentów oprogramowania. Przykładowo: PiesBuda to nazwy pakietów. Jeśli wymienimy cały pakiet Pies na innego Psa, to ten będzie wiedział, jak posługiwać się Budą. Analogicznie, jeśli wymienimy Budę, to Pies również sobie poradzi.

RZ1itsNGEk2AJ
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Takie właśnie jest założenie diagramu pakietów – podzielenie programu na kilka komunikujących się ze sobą pakietów, które są niezależne.

Dzięki takiemu podziałowi możemy edytować jedną z funkcji w programie bez obawy, że popsujemy coś w innym miejscu, które jest pośrednio zależne od tej funkcji.

RrbQ6DknQXabF
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Zamówienie oraz Realizacja zamówienia to klasy, zatem – jak już wcześniej wspomnieliśmy – nie definiujemy ich metod. Zakładamy, że klasa stanowi kompletną całość.

W diagramie pakietów możemy zaznaczać również zależności pomiędzy poszczególnymi klasami, jednak należy to robić tylko w ramach poszczególnych pakietów. Warto dodać, że te elementy także powinniśmy uwzględnić w diagramie klas.

Pomiędzy poszczególnymi pakietami mogą istnieć inne zależności. W tym e‑materiale omówimy tylko podstawowe dziedziczenie, które działa analogicznie do dziedziczenia klas.

RRU0jVqYnyNe6
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Przedstawiony zapis oznacza, że Pakiet A dziedziczy po Pakiecie B, przejmując wszystkie klasy, jakie były w nim umieszczone. Dodatkowo możemy definiować zakres wzajemnej widoczności pakietów, jednak w tym wypadku nie będziemy tego robić, ponieważ nie jest to kluczowe.

Omawiając poszczególne diagramy, wspomnieliśmy niektóre elementy jedynie pobieżnie. Wynika to z faktu, że diagramy można rozbudowywać, ale nie przy każdym projekcie zachodzi taka potrzeba.

Warto pamiętać, że inżynieria oprogramowaniainżynieria oprogramowaniainżynieria oprogramowania, a dokładniej: projektowanie oprogramowania, jest bardzo złożonym procesem. Nie sposób omówić wszystkich jego aspektów, nie tracąc jednocześnie z oczu głównego celu tej serii e‑materiałów, jakim jest stworzenie gry.

Projekt Snake

Zacznijmy od diagramu aktywności. Gracz wykonuje pewne czynności, które mogą być katalizatorami innych zależności, dlatego też schemat będzie większy od poprzednich. Skupmy się na tym, co poszczególne akcje gracza spowodują lub będą mogły powodować.

RZvNZdHx6IgxT
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Dla uproszczenia tworzymy czynność Pojawienie się węża, której użyjemy w kolejnych diagramach. Składa się ona z dwóch kolejno wykonywanych akcji: pojawienia się głowy węża na środku ekranu oraz skierowania głowy węża „na północ”.

RDnwcRzntcjya
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Tworzenie diagramu jest procesem. Jesteśmy w stanie ocenić, czy czegoś w nim brakuje, dopiero gdy go skończymy (lub po przejściu do rysowania kolejnej czynności). Jeśli się zorientujemy, że czegoś w diagramie nie uwzględniliśmy, powinniśmy go poprawić. Diagram aktywności przypomina pod tym względem programowanie.

Diagram przedstawiający czynność poruszania się węża nie uwzględnia zatrzymania ruchu, gdy zostanie włączona pauza. Błąd ten wymaga korekty.

R1MyznH4kUQlB
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Zapisaliśmy kilka czynności, na podstawie których możemy stworzyć kod. Diagram aktywności możne przywodzić na myśl pseudokod zapisany w formie schematu blokowego – jednak to nie jest to samo i należy o tym pamiętać.

RGltqovQ83MHY
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Kolejny diagram prezentuje rozgrywkę z uwzględnieniem współbieżnego sterowania. W grze Snake wąż nie oczekuje, aż klikniemy przycisk. Porusza się niezależnie od naszych akcji.

RRu4OnH7ouAb6
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Diagram wyjaśnia funkcjonowanie rozgrywki, uwzględniając aktywności zarówno użytkownika, jak i samej gry. Przejdźmy do stworzenia diagramu pakietów. Będzie on prosty, ponieważ sama gra ma nieskomplikowaną strukturę.

R379KDtByLswC
Źródło: Contentplus.pl Sp. z o.o., licencja: CC BY-SA 3.0.

Na koniec warto zaznaczyć, że wszystkie trzy pakiety powinny mieć swobodny dostęp do siebie nawzajem.

Słownik

inżynieria oprogramowania
inżynieria oprogramowania

proces polegający na stosowaniu podejścia inżynierskiego do tworzenia oprogramowania; wiedza techniczna, które obejmuje każdą fazę życia oprogramowania – od zaprojektowania go, przez implementację, konserwację, a ostatecznie powstanie gotowego produktu

klasa
klasa

blok kodu definiujący lub częściowo definiujący zachowania oraz dopuszczalny stan obiektów

węzeł sterowania
węzeł sterowania

miejsce, z którego dalej wykonuje się dane akcje bądź czynności i się je śledzi; pierwszy węzeł sterowania pojawia się na samym początku diagramu aktywności