Kompozice a agregace se v praxi používají, když chceme v případě binárních asociací zdůraznit princip celku a jeho částí: motor je součástí auta, procesor je součástí počítače, firma je složena z jednotlivých oddělení apod.
Poznámka: Text tohoto článku můžete považovat za ukázku z připravované knihy UML pro analytiky, která vyjde na přelomu února a března příštího roku. Pokud nechcete čekat a dozvědět se více, pak 6. a 7. prosince 2018 můžete navštívit mé školení stejného názvu, kde mj. dostanete aktuální podobu textu s příslibem výtisku zdarma.
Z pohledu UML o agregaci hovoříme ve chvíli, kdy je nějaká instance použita k tomu, aby seskupila dohromady množinu jiných instancí. Tato agregace je dvojího druhu: sdílená (anglicky shared) a složená (anglicky composite). Aby to nebylo tak jednoduché, tak modelovací žargon používá termín agregace pro sdílenou agregaci a kompozice pro složenou agregaci. Jelikož je to natolik zaběhnuté, budu to používat také. Pokud tedy v následujícím textu bude uvedena pouze agregace bez bližší specifikace, je tím myšlena sdílená agregace.
UML nám říká, že sémantiku pro sdílenou agregaci definuje autor modelu, případně vyplývá z toho, pro jakou doménu tvoříme náš model. Kompozice je pak přísnější agregace, která vyžaduje, aby část jsoucí v celku, byla v jednu dobu právě v jednom takovém celku. A dále dodává, že pokud je rušen celek, nejprve jsou rušeny všechny jeho části (případně tyto části mohou být z celku vyňaty, dává-li to smysl, a tedy se neruší. Upozorňuji, že se stále jedná o sémantiku danou UML standardem. Část lidí pracující s UML zarputile tvrdí, že to nejde.).
Sdílená agregace se zakresluje prázdným kosočtvercem na konci asociace u celku, kompozice pak plným (černým) kosočtvercem tamtéž.
Na uvedeném příkladu je vidět, že jedna třída je definovaná jako část, ale současně může být celkem (v našem případě je to třída Kraj). Tento postup však nesmí být cyklický. Dále z podmínky, že v případě kompozice smí být část maximálně v jednom celku, plyne, že násobnost konce asociace u celku může být pouze 1 nebo 0..1 (viz následující obrázek).
U sdílené agregace toto samozřejmě neplatí. Tam může být část v jeden okamžik součástí více celků. Na prvním uvedeném příkladu vidíme, že se studijní program skládá z předmětů, ale jeden předmět může být součástí více studijních programů (např. čeština bude na středních školách ve všech studijních programech). Násobnost tedy může být dle následujícího obrázku.
Dále platí pravidlo, že agregace i kompozice je asymetrický vztah, tedy že pouze jeden konec binární asociace smí být označen jako celek.
Mezi uživateli UML se občas (bohužel) vyskytne zbytečná debata o tom, zda v případě kompozice je možné část dát do jiného celku nebo zda může existovat sama o sobě. Jeden tábor horlivě tvrdí, že ne a jako argument používá příklad, že strom má listy a ty nelze převěsit na jiný strom. Druhá skupina, která říká, že část lze dát do jiného celku, zase používá argument podobný tomu na obrázku s motorem. Motor přeci lze přehodit z jednoho auta do druhého, případně ho mít na skladě jako náhradní díl. Kde je pravda? UML na to bohužel neodpovídá (resp. říká, jak již bylo řečeno, že lze část z celku vyjmout, ale již se nic neříká o vložení do jiného celku).
Zkusme to ale celé pojmout rozumně. Kompozice lze v principu rozdělit do šesti základních skupin (podrobněji se o tom můžete dozvědět na této stránce):
- Kompozice komponent: auto má motor, kniha má kapitoly, diskuse má příspěvky.
- Kompozice materiálů: kapučíno se skládá z mléka a kávy, chleba je z části obilí, auto je částečně z kovu.
- Kompozice porcí/dílů: chleba lze rozdělit na krajíce, tunu lze rozdělit na kilogramy.
- Územní kompozice: Radotín je částí Prahy, pokutové území je součástí hřiště, úpatí je součástí hory.
- Kompozice typu člen skupiny: strom je součástí lesa, cyklista je součástí pelotonu, zabrušovač Míla Rozner je členem nacistické organizace SPD.
- Partnerská kompozice: Jan Werich byl součástí umělecké dvojice V+W.
Zkuste si přestavit situace, kdy z každého typu kompozice odeberete část. Někdy můžeme dál mluvit o celku, někdy nikoliv. Pokud v diskusi smažu jeden příspěvek, stále to může být diskuse, leckdy přínosnější, ale příspěvek sám o sobě význam nemá. Z kapučína mléko už asi jednoduše nedokážu dát pryč, ale pokud se mi to povede, tak mléko samo o sobě fungovat může. Odeberu-li byť jediné kilo z tuny, už to není tuna. Cyklista, který se vydá do úniku, již není součástí pelotonu, leč peloton funguje nadále a cyklista také. Skvělá dvojice V+W by bez Voskovce či bez Wericha nebyla dvojicí (Podobně např. sdružení ANO by bez bývalého estébáka, současného fašisty a usvědčeného podvodníka a lháře Babiše zaniklo stejně, jako se to stalo VeVerkám.). Pokud se tedy nad tím zamyslíme, někdy můžeme prvek z celku odebrat, případně jej vložit do jiného celku, nebo ho necháme úspěšně fungovat samotného, jindy to prostě dělat nebudeme.
Problém může nastat ve chvíli, kdy špatně určíme typ kompozice. Pak může docházet ke komickým závěrům ve chvíli, kdy předpokládáme, že kompozice je bez výjimky transitivní relací.
Transitivní relace je taková relace, kdy platí, že pokud a je v relaci s b a současně b v relaci s c, pak a je v relaci s c. Např. relace „porovnání větší než“ transitivní určitě je: a > b a b > c, pak i a > c. Naopak např. relace „je rodič“ není transitivní. Pokud Petr je rodič Jany a Jana je rodič Pavla, tak určitě neplatí, že Petr je rodič Pavla.
Ukažme si to opět na příkladu. Na následujícím obrázku vidíme, že auto se skládá z motoru a motor z pístů. Zde relace určitě transitivní je, neboť docházíme ke správnému tvrzení, že auto se skládá z pístů.
Ovšem v případě kombinací typů kompozice můžeme dojít sice k úsměvnému, leč špatnému tvrzení. Podívejte se na další obrázek. Asi budete se mnou souhlasit, že rameno nějaké osoby určitě není členem nějaké zájmové skupiny. Přesto z pohledu UML jsou všechny typy kompozice zakreslovány shodně.
Zkusme si to shrnout:
- Část lze v některých případech přehodit z jednoho celku do jiného, v jiných ne (nedává to smysl nebo je to nemožné). UML to však nezakazuje, tedy to můžeme ve smysluplných případech používat.
- V některých případech může část fungovat i sama o sobě bez toho, aby byla v nějakém celku.
- Je třeba si uvědomit typ kompozice a dle toho aplikovat, nebo naopak neaplikovat transivitu.