Czym jest diagram struktur złożonych#
Diagram struktur złożonych (composite structure diagram) pokazuje wewnętrzną budowę klasyfikatora strukturalnego oraz sposób współpracy jego części. Ujawnia role odgrywane przez elementy wewnętrzne, punkty interakcji na granicy i połączenia między nimi. Jest przydatny wtedy, gdy sam diagram klas lub komponentów pokazuje „czarną skrzynkę”, a trzeba wyjaśnić, jak jej wnętrze realizuje zachowanie albo udostępniany kontrakt.
Diagram nie ogranicza się do klasy. Strukturę wewnętrzną można modelować dla odpowiednich klasyfikatorów, takich jak klasa lub komponent, a także w kontekście współpracy. Najważniejsze elementy to klasyfikator strukturalny, części (parts), porty (ports) oraz łączniki (connectors). Rysunek opisuje możliwą organizację struktury instancji, nie pojedynczy zestaw obiektów w konkretnym uruchomieniu.
W nomenklaturze polskiej spotyka się również określenie „diagram struktury złożonej”. W tym artykule „struktura złożona” oznacza diagram UML pokazujący wnętrze klasyfikatora; nie należy mylić tego pojęcia z relacją kompozycji na diagramie klas.
Kiedy używać diagramu#
Wybierz ten diagram, gdy istotne jest, z jakich części składa się instancja klasyfikatora, jakie role odgrywają te części, przez które porty zachodzi interakcja i jak połączenia przekazują żądania między elementami. Może pomóc opisać:
- wewnętrzną strukturę komponentu lub klasy, której zachowanie jest realizowane przez współpracujące części;
- przypisanie odpowiedzialności do części pełniących określone role;
- granicę między interfejsem zewnętrznym a implementacją wewnętrzną;
- przepływ żądań przez porty i łączniki delegujące;
- połączenia części wewnętrznych, które korzystają z siebie nawzajem;
- współpracę, której role są używane przez większy klasyfikator.
Jeśli trzeba pokazać wyłącznie publiczne usługi i zależności pomiędzy modułami, prostszy może być diagram komponentów. Jeśli interesują nas klasy i ich relacje, wybierz diagram klas. Diagram struktur złożonych jest bardziej szczegółowy: koncentruje się na wnętrzu i interakcjach części w ramach konkretnego właściciela.
Klasyfikator strukturalny i jego części#
Klasyfikator strukturalny (structured classifier) jest klasyfikatorem, którego strukturę wewnętrzną można opisać za pomocą części, portów i łączników. Na diagramie pokazuje się go jako ramkę lub obszar opisany nazwą właściciela. Wewnątrz znajdują się części i ich połączenia.
Część jest właściwością właściciela, która określa rolę instancji uczestniczącej w strukturze. Zapis często ma postać nazwaRoli: Typ, np. zamówienia: ObsługaZamówień. Część nie jest po prostu mniejszym prostokątem ani dowolną klasą z diagramu. Jej nazwa określa rolę w strukturze, a typ mówi, jakiego klasyfikatora instancja tę rolę spełnia.
W modelu można określić krotność części, np. [1], [0..*] lub [2], aby opisać, ile instancji danego typu występuje w strukturze. Krotność części może zależeć od konfiguracji instancji właściciela. Nie jest tym samym co krotność końca asocjacji na diagramie klas, choć oba zapisy używają przedziału liczbowego.
Właściciel może zawierać części o różnych typach. Dwie części tego samego typu mogą odgrywać różne role; wtedy ich nazwy pomagają odróżnić odpowiedzialności. Gdy model wymaga wielu konfiguracji, nie próbuj upychać każdej z nich w jednym rysunku. Pokaż reprezentatywny wariant, warunek wyboru lub oddzielne widoki.
Porty i interfejsy#
Port jest określonym punktem interakcji klasyfikatora z otoczeniem albo z częściami wewnętrznymi. Jest umieszczany na granicy klasyfikatora lub na części. Może udostępniać interfejsy, których właściciel dostarcza, oraz wymagać interfejsów, z których korzysta. Port jest więc bardziej precyzyjnym punktem współpracy niż sama ogólna linia do prostokąta.
Interfejs udostępniany (provided interface) określa usługi oferowane przez element na zewnątrz. W notacji „lizaka” jest przedstawiany jako kółko. Interfejs wymagany (required interface) opisuje usługi, których element potrzebuje; często używa się oznaczenia półokrągłego gniazda („socket”). Interfejs określa kontrakt, a port wskazuje miejsce, przez które odbywa się współpraca.
Nie każdy port musi mieć jawnie narysowane oba rodzaje interfejsu. Port bez widocznej listy kontraktów może być uproszczeniem diagramu, ale czytelnik nie powinien być zmuszony do zgadywania, czy punkt służy do dostarczania, czy do wymagania usługi. Nazwij port lub opisz kontrakt w tekście, kiedy wpływa to na interpretację.
Port może być sprzężony z zachowaniem klasyfikatora, z jego wewnętrzną częścią lub z oboma wariantami. To, czy port jest publiczny albo chroniony i jak ogranicza interakcję, zależy od jego właściwości modelu. Diagram powinien pokazywać szczegóły tylko wtedy, gdy odbiorca musi je znać.
Łączniki: assembly i delegation#
Łącznik (connector) określa możliwą ścieżkę komunikacji między rolami struktury. Zwykle łączy części albo porty. W strukturze złożonej istotne są dwa wyspecjalizowane rodzaje połączeń.
Łącznik montażowy#
Łącznik montażowy (assembly connector) łączy część wymagającą usługi z częścią lub portem udostępniającym odpowiedni interfejs. Pokazuje, jak wewnętrzni uczestnicy współpracują. Warunkiem sensownego połączenia jest zgodność wymaganych i udostępnianych kontraktów; sama bliskość elementów nie ustanawia kompatybilności.
Łącznik może być prostą linią w diagramie, ale jego semantyka wynika z podłączonych ról i portów. Jeżeli rysunek nie pokazuje interfejsów, podpis może wyjaśnić, czego dotyczy połączenie. Nie opisuje on automatycznie protokołu transportowego ani kolejności wywołań.
Łącznik delegujący#
Łącznik delegujący (delegation connector) wiąże interakcję z portem na zewnętrznej granicy klasyfikatora z wewnętrzną częścią lub jej portem. Przekazuje zachowanie zewnętrzne do elementu realizującego je wewnątrz. Dzięki temu diagram może pokazać, że klient rozmawia z właścicielem przez jego port, a właściciel kieruje żądanie do odpowiedniej części.
Delegacja pomaga oddzielić publiczny kontrakt od wewnętrznego podziału odpowiedzialności. Zmiana wewnętrznej struktury nie musi wymagać zmiany portu, jeśli zachowany zostaje kontrakt zewnętrzny. To jednak decyzja architektoniczna, którą trzeba utrzymywać; rysunek sam nie gwarantuje stabilności interfejsu.
Przykład: wnętrze modułu obsługi zamówień#
Poniższy diagram pokazuje komponent sklepu, jego port udostępniający API oraz dwie części wewnętrzne: obsługę zamówień i adapter płatności. Port deleguje żądania do części obsługującej zamówienia, a część zamówień ma wewnętrzne połączenie z adapterem płatności.
Zewnętrzny port znajduje się na granicy sklepu; połączenie od niego do części wewnętrznej ilustruje delegację. Połączenie między obsługą zamówień i adapterem jest wewnętrzną ścieżką współpracy części. W uproszczonym rysunku PlantUML relacje są opisane etykietami; nie pokazano typowanych interfejsów ani pełnych symboli „lizaka” i „gniazda”.
Diagram nie twierdzi, że płatność jest zawsze wykonywana synchronicznie ani że adapter łączy się z konkretnym zewnętrznym dostawcą. Nie pokazuje także liczby instancji części, ich cyklu życia ani przepływu błędów. Te informacje wymagają dalszych ograniczeń lub diagramów zachowania.
Jak czytać diagram struktur złożonych#
- Zidentyfikuj właściciela struktury oraz granicę, która oddziela jego wnętrze od otoczenia.
- Odczytaj nazwy ról części i ich typy; ustal, jaką funkcję pełni każda część.
- Sprawdź krotności części, jeśli są pokazane.
- Znajdź porty na granicy właściciela i na częściach oraz ustal, jakie interfejsy udostępniają lub wymagają.
- Prześledź łączniki montażowe między częściami.
- Prześledź łączniki delegujące od portów zewnętrznych do wewnętrznych realizatorów.
- Sprawdź, czy wymagane i udostępniane interfejsy są zgodne.
- Odróżnij strukturę możliwą od konkretnego wykonania w czasie.
Warto odczytywać linie w kontekście końców. Sama linia może reprezentować różne relacje w zależności od tego, czy łączy części, porty, port z częścią, czy element z granicą właściciela. Jeśli narzędzie stosuje uproszczoną notację, podpisy i opis powinny wyjaśnić intencję.
Jak przygotować diagram#
1. Wybierz strukturę do otwarcia#
Nie pokazuj wnętrza każdego elementu systemu. Wybierz klasyfikator, którego wewnętrzna współpraca jest potrzebna do wyjaśnienia zachowania, kontraktu lub odpowiedzialności.
2. Określ role części#
Wypisz uczestników realizujących strukturę i przypisz im role. Oddziel nazwę roli od typu, który tę rolę wypełnia. Jeżeli dwie części mają ten sam typ, użyj różnych nazw ról.
3. Ustal punkty interakcji#
Zdecyduj, jakie usługi klasyfikator udostępnia na zewnątrz, czego potrzebuje i przez które porty odbywa się komunikacja. Pokaż interfejsy tam, gdzie ich zgodność jest ważna.
4. Połącz części i porty#
Dodaj łączniki montażowe dla wewnętrznych współprac oraz delegujące dla przekazywania interakcji z granicy do części. Nie mieszaj obu ról tylko dlatego, że w narzędziu mają podobny wygląd.
5. Ogranicz i sprawdź model#
Zweryfikuj krotności, zgodność interfejsów, kierunek delegacji oraz zgodność przykładu z tekstem. Zostaw tylko te szczegóły, które służą celowi. Jeśli odbiorca potrzebuje również sekwencji wywołań, dodaj osobny diagram zachowania.
Struktura złożona a kompozycja#
Słowa „struktura złożona” i „kompozycja” mogą brzmieć podobnie, ale odnoszą się do różnych zagadnień. Diagram struktur złożonych pokazuje role, części, porty i łączniki wewnątrz klasyfikatora. Kompozycja jest szczególnym rodzajem asocjacji na diagramie klas, oznaczanym wypełnionym rombem i opisującym relację całość–część.
Części struktury mogą być typowane przez klasyfikatory i opisują rolę instancji w wewnętrznej budowie. Nie należy automatycznie wnioskować, że każda część w diagramie struktur złożonych oznacza semantykę kompozycji klasowej, ani że wypełniony romb zastąpi porty i łączniki.
Różnica względem diagramu komponentów#
Diagram komponentów pokazuje moduły, ich kontrakty i współpracę na poziomie architektury komponentowej. Diagram struktur złożonych otwiera wnętrze konkretnego klasyfikatora i pokazuje jego części oraz sposób, w jaki porty przekazują komunikację. W niektórych narzędziach notacje są podobne, bo komponenty również mogą mieć porty i strukturę wewnętrzną.
Wybór zależy od pytania: „Jakie moduły komunikują się w systemie?” wskazuje na diagram komponentów; „Jak wnętrze tego modułu jest zorganizowane i jak zewnętrzny port wiąże się z jego częściami?” wskazuje na strukturę złożoną.
Typowe błędy#
- Pokazywanie wyłącznie klas w prostokątach. Diagram powinien wyjaśniać role, porty i połączenia struktury, jeśli to one są celem.
- Mylenie części z klasą. Część ma nazwę roli i typ; przedstawia uczestnictwo w strukturze właściciela.
- Brak właściciela lub granicy. Bez niej nie wiadomo, co jest wnętrzem, a co otoczeniem.
- Traktowanie portu jako dowolnego punktu na krawędzi. Port określa interakcję i może być powiązany z wymaganymi lub udostępnianymi interfejsami.
- Mylenie łącznika montażowego z delegującym. Jeden łączy współpracujące części, drugi przekazuje interakcję zewnętrzną do wnętrza.
- Niezgodne interfejsy po obu stronach. Sprawdź, czy część rzeczywiście oferuje kontrakt wymagany przez klienta.
- Zakładanie, że diagram pokazuje przebieg czasu. Struktura połączeń nie opisuje kolejności komunikatów ani algorytmu.
- Zamiana struktury złożonej w kompozycję klas. Są to różne konstrukcje i różne perspektywy modelu.
- Nadmierne otwieranie wnętrza. Pokaż tyle szczegółów, ile wymaga wyjaśnienie, a głębsze poziomy przenieś na osobne diagramy.
- Przypisywanie uproszczonym ikonom pełnej semantyki. Jeśli renderer nie pokazuje dokładnej notacji UML, opisz rodzaj relacji tekstem i oznacz ograniczenie widoku.
Co diagram struktur złożonych pokazuje, a czego nie#
Diagram struktur złożonych pokazuje, z jakich ról składa się struktura klasyfikatora, przez jakie porty odbywa się komunikacja i jak wewnętrzne części są połączone. Jest szczególnie przydatny do wyjaśnienia relacji między kontraktem zewnętrznym a realizacją wewnętrzną.
Nie opisuje samodzielnie szczegółów algorytmu, kolejności zdarzeń, konkretnego stanu instancji ani rozmieszczenia na serwerach. Uzupełnij go diagramem sekwencji, obiektów, komponentów lub wdrożenia, gdy te pytania należą do zakresu dokumentacji.