Podręcznik
1. Specyfikowanie słownika dziedziny
1.2. Identyfikowanie pojęć w słowniku dziedziny
Aby móc przystąpić do tworzenia słownika dziedziny najpierw powinniśmy zrozumieć czym taki słownik powinien być. Słownik dziedziny w inżynierii wymagań oprogramowania jest uporządkowanym zbiorem wyrazów i fraz, wraz z ich znaczeniami, za pomocą których można opisać wszystkie pojęcia występujące w określonym fragmencie rzeczywistości, dla którego budujemy system oprogramowania.
Aby wyjaśnić rolę słownika w specyfikacji wymagań posłużymy się porównaniem do powieści. Na rysunku 1.1 mamy fragmenty opisujące akcję (fabułę), czyli pewne zdarzenia układające się w pewien ciąg. Oczywiście, rysunek jest pewnym uproszczeniem, gdyż akcja może mieć zdarzenia dziejące się równolegle. Akcja czasami jest przerywana i autor dokonuje „opisu przyrody”. Opisy te mają na celu przedstawianie cech występujących w akcji osób, przedmiotów czy miejsc. Opisy te mogą być uporządkowane i tworzyć mapę. Mapa określna przestrzenne zależności między poszczególnymi elementami występującymi w otoczeniu (domy, rzeki, góry, …) i wśród których toczy się akcja. Oczywiście, w specyfikacji wymagań nie rysujemy mapy terenu (czasami takie mapy spotyka się jako ilustracje w powieściach). Zamiast tego, tworzony jest graficzny model dziedziny problemu w postaci diagramu zawierającego pojęcia i relacje między nimi.
Rysunek 1.1: Konstrukcja specyfikacji wymagań z „mapą terenu”
Rezultatem analizy wymagań użytkownika pod kątem używanego słownictwa jest słownik dziedziny, który definiuje wszystkie pojęcia występujące w specyfikacji. Co jest istotne, słownik dziedziny zaczynamy tworzyć już na poziomie wizji systemu, a potem rozbudowujemy podczas tworzenia wymagań użytkownika i wymagań oprogramowania. Na poziomie wymagań oprogramowania słownik będzie uzupełniony o pojęcia związane ze szczegółami funkcjonowania systemu, o czym będziemy mówili w dalszej części podręcznika. W rezultacie, otrzymujemy spójny model dziedziny, który powinien stanowić schemat kompletnej specyfikacji wymagań z wyraźnie wyróżnionym, centralnym słownikiem dziedziny. Kluczowe jest tutaj założenie, że unikamy definiowania pojęć wewnątrz opisów poszczególnych wymagań. W ten sposób uzyskujemy konstrukcję specyfikacji wymagań podobną do mapy terenu (patrz rys. 1.1).
Przykład identyfikacji pojęć w treści wymagań widzimy na rysunku 1.2. Jak widać, pojęcia zostały wyróżnione poprzez umieszczenie ich w nawiasach kwadratowych i zapisanie kursywą. Taka notacja jest oczywiście przykładowa i wyróżnianie pojęć może być dokonane w inny sposób. Pojęcia możemy znajdować w nazwach wymagań (przypadków użycia, historii użytkownika, cech systemu, …) oraz w różnych elementach ich opisu (scenariuszach, konwersacjach, …).
Rysunek 1.2: Identyfikacja pojęć do słownika dziedziny
Bardzo istotnym problemem podczas identyfikacji pojęć słownikowych jest występowanie synonimów i homonimów. Homonimy to słowa, które są pisane (i wymawiane) identycznie, ale posiadają różne znaczenia. Z kolei, synonimy, to słowa, które są pisane różnie, ale posiadają takie same znaczenia. Odpowiednie przykłady widzimy na rysunku 1.3. Występowanie synonimów i homonimów jest spowodowane przede wszystkim tym, że w tworzeniu specyfikacji wymagań uczestniczą różne grupy osób, które mogą używać różnego słownictwa. Przykładem są różne działy w danej organizacji, które wykształciły swoje słownictwo niezależnie od innych działów. Powstawaniu homonimów i synonimów sprzyja również utrzymywanie specyfikacji wymagań w postaci „płaskiego” dokumentu. W takim dokumencie słownik jest osobną sekcją na końcu, której aktualizacja jest zadaniem żmudnym i pracochłonnym. W takiej sytuacji, identyfikacja sprzeczności w słowniku jest bardzo trudna.
Rysunek 1.3: Przykładowe synonimy i homonimy w słowniku
Problem homonimów powinien być rozwiązany poprzez uściślenie nazewnictwa. Konieczne jest wyraźne rozróżnienie pojęć poprzez np. dodanie dodatkowych słów, np. „konto” à „konto osobiste” oraz „konto” à „konto bankowe”. W przypadku synonimów sytuacja może być bardziej skomplikowana. Najprostszym rozwiązaniem jest oczywiście zdecydowanie się na użycie jednego z synonimów w całej specyfikacji. Jest to jednocześnie rozwiązanie skutkujące najbardziej spójną specyfikacją.
1.1. Formułowanie słownika dziedziny
Słownik, podobnie jak cała specyfikacja wymagań, najczęściej tworzony jest w formie dokumentu tekstowego w odpowiednim edytorze tekstu, co ilustruje rysunek 1.4. Zarządzanie słownikiem odbywa się poprzez ręczną aktualizację poszczególnych pojęć oraz ich definicji. Wymaga to sporego nakładu pracy i jest powodem wielu błędów.
Rysunek 1.4: Słownik w postaci dokumentu
Często używaną formą słownika dziedziny jest diagram (forma graficzna). Diagram pozwala zaprezentować słownik dziedziny jago graf powiązanych ze sobą pojęć, co ilustruje rysunek 1.5. Jak można zauważyć, wszystkie pojęcia z rysunku 1.5 zostały umieszczone na diagramie i połączone zgodnie z relacjami zawartymi w ich opisach. Opisy pojęć zostały na diagramie pominięte.
Rysunek 1.5: Słownik w postaci diagramu
Wizualne przedstawienie relacji między pojęciami umożliwia szybkie rozeznanie w strukturze danej dziedziny problemu. Zachowujemy jednocześnie wszystkie zalety zapisu tekstowego, gdyż do wszystkich pojęć na diagramie możemy dołączyć opisy tekstowe. Uzyskujemy w ten sposób omówiona na początku „mapę terenu”, która ułatwia zrozumienie całej specyfikacji wymagań.
Diagramy klas stanowią najbardziej uniwersalną i prawdopodobnie najbardziej rozpowszechnioną formę graficznej reprezentacji słownika dziedziny. Podstawowym elementem diagramu klas jest oczywiście klasa, reprezentująca pojęcie w danej dziedzinie problemu. Na rysunku 1.6 przedstawione zostały różne dopuszczalne reprezentacje graficzne klas w języku UML. Najprostszą reprezentacją klasy jest prostokąt zawierający wyśrodkowaną nazwę klasy. Ikona klasy może zawierać kilka przegródek, oddzielonych liniami poziomymi. Jedna z przegródek może zawierać tzw. „metki” (ang. tag), które odpowiadają atrybutom wymagań omówionym w poprzednich rozdziałach.
Rysunek 1.6: Przykładowe klasy z pokazanymi atrybutami i metkami
Po nazwie atrybutu możemy umieścić jego typ zapisany po dwukropku. Na poziomie specyfikacji wymagań użytkownika typ może być czasami istotny, chociaż w większości przypadków wystarczy samo podanie nazwy atrybutu. Zwróćmy uwagę na to, że język UML nie definiuje dopuszczalnych typów. Dlatego też możemy określić własne nazwy typów, np. „tekst”, „napis”, „liczba”. Czasami wskazane jest zdefiniowanie typów, których wartości są wyliczane jako lista. Takie typy wyliczeniowe (ang. enumeration) reprezentowane są podobnie jak klasy w postaci prostokątów z nazwą. Nad nazwą takiego typu umieszczamy dodatkowe oznaczenie «enumeration», a w drugiej przegródce podajemy listę dopuszczalnych wartości. Przykładowy typ wyliczeniowy wraz z przykładem jego zastosowania został przedstawiony na rysunku 1.7.
Rysunek 1.7: Przykłady zastosowania typów
Relacja asocjacji definiuje możliwe związki między obiektami klas (w szczególności – związki między obiektami tej samej klasy). Klasy na końcach asocjacji mogą mieć zdefiniowane określone role. Asocjacje oznaczamy linią łączącą odpowiednie klasy. Przykłady asocjacji przedstawia rysunek 1.8. Jak widzimy, między dwoma klasami możemy zdefiniować kilka asocjacji, które określają różne role dla relacji między obiektami. Zgodnie z diagramem, konkretna osoba może posiadać dowolnie dużo (od 0 do wielu) samochodów oraz może kierować (w danej chwili) maksymalnie jednym samochodem (krotność od zera do jednego). Z kolei samochód może mieć dokładnie jednego właściciela oraz maksymalnie jednego kierowcę. Na rysunku 1.8 widzimy również asocjację dotyczącą tylko klasy „Osoba” (asocjacja „zawinięta”). Zgodnie w tym fragmentem modelu, dana osoba ma dokładnie dwóch rodziców oraz może mieć dowolnie dużo dzieci.
Rysunek 1.8: Przykładowe zastosowania asocjacji
Specjalną własnością asocjacji jest tzw. nawigowalność (skierowanie asocjacji). Nawigowalność oznacza możliwość efektywnego osiągnięcia obiektów jednej klasy przez obiekty drugiej klasy. W specyfikacji wymagań może to odpowiadać użyciu nazwy pojęcia w definicji innego pojęcia. Nawigowalność asocjacji oznaczamy poprzez dodanie grotu strzałki na końcu asocjacji, co ilustruje przykład na rysunku 1.9. Z rysunku wynika, że obiekty klasy „Dowód rejestracyjny” mają dostęp do danych odpowiadających im samochodów, natomiast obiekty klasy „Samochód” nie mają zdefiniowanego dostępu do danych przypisanych do nich dowodów rejestracyjnych.
Rysunek 1.9: Przykład asocjacji nawigowalnej
Specjalnym rodzajem asocjacji są relacje agregacji. Stosujemy je, kiedy potrzebne jest odzwierciedlenie związku między grupą, a jej elementem lub elementami. Relacja agregacji jest zatem relacją grupowania, na przykład grupowania składników (części) pewnej całości. Relacja agregacji stosuje wszystkie elementy notacji asocjacji i dodatkowo jest wyróżniana poprzez umieszczenie małej ikony rombu po jednej stronie relacji. Romb umieszczany jest przy tej klasie, która stanowi całość. Przykład relacji agregacji widzimy na rysunku 1.10. Klasa „Samochód” stanowi element grupujący (całość), a klasa „Bagaż” definiuje elementy grupowane (składniki).
Rysunek 1.10: Przykład zastosowania agregacji i kompozycji
Rysunek 1.10 zawiera również relację między klasami „Samochód” i „Silnik”. Jest ona oznaczona podobnie jak relacja agregacji, lecz ikona rombu jest wypełniona. Jest to relacja kompozycji, która stanowi „silniejszą” wersję relacji agregacji. Reprezentuje ona związek pomiędzy całością a jej integralnymi częściami. Istotną cechą relacji kompozycji jest zasada, że obiekty odpowiadające składnikom nie mogą być zawarte w więcej nić jednym obiekcie odpowiadającym całości. Inaczej mówiąc – w relacji kompozycji składniki nie mogą być dzielone między różne całości. Dlatego też, krotność po stronie całości nie może być większa niż 1. Dodatkowym wyróżnikiem relacji kompozycji jest to, że składniki zazwyczaj powstają i kończą swoje istnienie razem z całością, do której należą – czas życia składników jest ograniczony czasem życia.
Istotnym aspektem specyfikowania słownika dziedziny jest tworzenie taksonomii pojęć. W języku UML taksonomie tworzymy za pomocą relacji generalizacji-specjalizacji (w skrócie – generalizacji). Relacja generalizacji określa zależność pomiędzy klasami-pojęciami bardziej ogólnych i klasami-pojęciami bardziej specjalizowanych. Klasy specjalizowane „dziedziczą” po klasie ogólnej wszystkie jej atrybuty oraz relacje (asocjacje, agregacje, kompozycje, generalizacje). Oznacza to, że obiekty klasy specjalizowanej posiadają wszystkie elementy zdefiniowane w danej klasie, oraz dodatkowo – wszystkie elementy pochodzące z klasy ogólnej. Relacje generalizacji oznaczamy strzałką z dużym grotem w kształcie trójkąta. Strzałka zwrócona jest od klasy specjalizowanej do klasy ogólnej (wskazuje na klasę ogólną). Przykłady zastosowania relacji generalizacji widzimy na rysunku 1.11.
Rysunek 1.11 Przykład zastosowania generalizacji i klas abstrakcyjnych
Stosując powyższe zasady budowy diagramów klas tworzymy słownik dziedziny w formie graficznej. Na rysunku 1.12 widzimy kontynuację i rozszerzenie przykładu z rysunku 1.4. Widzimy tutaj wszystkie rodzaje relacji między klasami-pojęciami. Jak widzimy, modele samochodów są składnikami cennika, który zawiera również pozycje cennika. Z kolei pozycje cennika zostały podzielone na pozycje dodatkowe oraz podstawowe. Wprowadziliśmy również ogólną klasę-pojęcie Osoba, od której specjalizuje Klient. To dodatkowe pojęcie przyda nam się w przyszłości, kiedy będziemy definiować inne pojęcia, które są specjalizacjami osoby (np. Pracownik, Kierowca, …).
Rysunek 1.12: Słownik w postaci diagramu klas
Diagram klas zawiera większość informacji, które moglibyśmy przedstawić w formie tekstowej. Ewentualne dodatkowe informacje definiujące pojęcia w słowniku graficznym możemy podać jako opisy klas-pojęć. Opisy takie nie są typowo widoczne na diagramie. Większość narzędzi CASE pozwala jednak na wygenerowanie odpowiedniego dokumentu, w którym obok diagramu będą widoczne wszystkie dodatkowe opisy.