Vzťahy v objektovom svete

Zdeno Jašek

13.08.2018

Tento článok obsahuje popis vzťahov medzi triedami v objektovo-orientovanom modeli s dopadmi na závislosti medzi nimi. Typy vzťahov sú demonštrované na nasledujúcom diagrame tried:

Diagram modeluje doménu evidencie zmlúv a faktúr pre zákazníka. Faktúra sa skladá z položiek faktúr, ktoré držia informácie o fakturovanom tovare, množstve a cene. K faktúre je priradený zákazník aj s adresou v samostatnej triede. Zákazník má priradený zoznam zmlúv, pričom zmluvy môžu byť paušálne alebo podľa používania. Cieľom modelu je názorne demonštrovať rôzne typy vzťahov medzi triedami, samotný model je pre vybranú doménu silne zjednodušený.

Vzťahy použité v modeli sú v nasledujúcom prehľade zoradené od najlepšieho po najhorší. Za meradlo kvality je považovaná stabilita modelu pri použití daného vzťahu, t.j. nakoľko bude použitie daného vzťahu vyvolávať rozsiahle zmeny v modeli pri nových používateľských požiadavkách na softvér.

1. Žiadny vzťah: Položka faktúry / Interval

Žiadny vzťah medzi triedami je ideálnym vzťahom z pohľadu údržby. Znamená to, že zmena jednej triedy nijako neovplyvní druhú triedu. Ak bude nutné upraviť triedu Položka faktúry podľa nových požiadaviek používateľa, určite sa takáto úprava nijako nedotkne triedy Interval.

2. Závislosť: Zmluva -> Faktúra

Trieda Zmluva nedrží odkaz na triedu Faktúra a naopak: ani trieda Faktúra nemá v uvedenom modeli odkaz na triedu Zmluva. Napriek tomu existuje závislosť triedy Zmluva na triede Faktúra. Zmluva obsahuje abstraktnú metódu „vytvor Faktúru“ s návratovou hodnotou typu Faktúra. Zmluva má teda závislosť na faktúre, hoci samotná trieda Zmluva nedrží v sebe referenciu na faktúru v podobe atribútu. Zmena v triede Faktúra môže mať dopad na fungovanie triedy Zmluva.

Tento druh závislosti sa v UML obvykle nezakresľuje, iba keď ju chce autor diagramu špeciálne zdôrazniť. Čiže prerušovaná šípka je nepovinná.

3. Asociácia: Faktúra -> Zákazník

Jeden zákazník sa môže objaviť na viacerých faktúrach. Navigačná šípka znamená, že z faktúry je možné zistiť zákazníka. Trieda Faktúra je závislá na triede Zákazník, t.j. zmeny v triede Zákazník môžu ovplyvniť fungovanie triedy Faktúra. Keďže šípka je jednosmerná, naopak to neplatí. Zmena v triede Faktúra nijako neovplyvní triedu Zákazník.

4. Agregácia: Zákazník -> Adresa

Agregácia je silnejšia forma asociácie. Platia pre ňu rovnaké tvrdenia ako pre asociáciu. Agregácia medzi zákazníkom a adresou hovorí, že adresa je integrálna súčasť zákazníka, s ktorou nesmie byť manipulované inak ako cez objekt Zákazník.

Triedy Zákazník a Adresa môžu byť do relačnej databázy ukladané dvomi spôsobmi:

  1. obe triedy môžu byť vkladané do jedinej tabuľky, ktorej polia budú zodpovedať atribútom oboch tried,
  2. každá z tried môže mať v SQL databáze svoju vlastnú tabuľku:

Použitie agregácie v objektovom modeli vyjadruje fakt, že adresa nesmie byť iným objektom ako Zákazník priamo vyberaná cez SELECT alebo ukladaná cez INSERT. Takže hoci je adresa uložená v samostatnej tabuľke a príkazom SELECT je možné vybrať ju bez kontextu zákazníka, použitie agregácie v modeli takýto prístup zakazuje.

Každá manipulácia s objektom typu Adresa sa musí diať s vedomím objektu typu Zákazník. Vďaka tomuto pravidlu môže prebrať trieda Zákazník zodpovednosť za vyplnenie atribútov triedy Adresa, t.j. považovať atribúty triedy Adresa za „svoje“. Cieľom obmedzenia je dosiahnuť konzistentné narábanie s dátami.

Objekty v agregácii sa obvykle modelujú ako nemenné („immutable“) a môžu byť využité pri funkcionálnom programovaní. Podrobnejšie sa tejto téme venuje článok v odkaze.

5. Kompozícia: Faktúra -> Položka faktúry

Kompozícia je ešte silnejšou väzbou medzi objektami ako agregácia. Platia teda pre ňu rovnaké tvrdenia ako pre agregáciu, ale navyše pridáva zviazanie životného cyklu objektu v kompozícii. Keďže faktúra sa skladá z položiek faktúry, životný cyklus objektov typu „Položka faktúry“ závisí od objektu „Faktúra“. Položka faktúry môže vzniknúť iba vtedy, ak faktúra existuje. Ak faktúra zanikne, zanikajú automaticky aj jej položky.

To je rozdiel oproti agregácii. Ak v použitej agregácii medzi zákazníkom a adresou zanikne objekt typu Zákazník, nemusí nutne zaniknúť referencovaný objekt typu Adresa. Pokiaľ na rovnakej adrese bývajú dvaja zákazníci, môže byť ten istý objekt priradený dvom rôznym zákazníkom. Vidieť to aj z horeuvedeného dátového modelu.

Pri kompozícii to však neplatí: so zánikom objektu typu Faktúra musí nutne zaniknúť aj objekt typu Položka faktúry. Položka faktúry nemá význam mimo kontextu faktúry. Zoznam položiek faktúry je v danom modeli modelovaný ako integrálna súčasť faktúry podobne ako číslo faktúry. Zoznam položiek s faktúrou vzniká aj zaniká, bez nej nemá význam.

Závislosti v asociácii, agregácii a kompozícii sú v smere šípky a platia pre ne rovnaké tvrdenia.

6. Dedičnosť: Paušálna zmluva -> Zmluva

Dedičnosť je najsilnejším typom vzťahu medzi dvomi triedami. Jej používanie je vhodné tam, kde sa využíva polymorfizmus. V uvedenom príklade je metóda „vytvor Faktúru“ abstraktná, t.j. jej implementácia je v triedach „Paušálna zmluva“ a „Zmluva podľa používania“. Dedičnosť býva častokrát používaná nesprávne – podrobnejší článok na túto tému je medzi odkazmi. Závislosť je opäť v smere šípky, t.j. zdedené triedy sú závislé na bázovej triede. Zmeny bázovej triedy majú obvykle silné dopady na dedené triedy, pretože dedičnosť porušuje princíp zapúzdrenosti.

7. Obojsmerná asociácia: Zákazník <-> Zmluva

Uvedený model umožňuje objektu typu Zmluva odpovedať na otázku, s akým zákazníkom bola uzatvorená. Rovnako objekt typu Zákazník dokáže odpovedať na otázku, aké zmluvy s ním boli uzatvorené. Hoci oba smery dávajú zmysel, použitie obojsmernej asociácie v objektovom modeli je veľmi nešťastné. Neexistuje ani vhodný príklad na použitie obojsmernej asociácie, pretože obojsmerná asociácia zavádza do objektov vzájomnú závislosť. Ak by nové požiadavky na softvér viedli ku zmene v triede Zákazník, zasiahne to triedu Zmluva a naopak: zmena v triede Zmluva môže ovplyvniť fungovanie triedy Zákazník. Triedy Zmluva a Zákazník sa stávajú z pohľadu zmien jednou triedou, ktorá sa vždy mení naraz. Obojsmerným asociáciám je vhodné vyhýbať sa.

Zrušenie obojsmernej asociácie medzi zmluvou a zákazníkom prináša otázky:

  1. Ktorý smer zachovať a ktorý zrušiť?
  2. Ako vyriešiť požiadavku, aby zmluva vedela, ktorému zákazníkovi patrí a zákazník vedel, ktoré zmluvy sú mu priradené?

OBE OTÁZKY SÚ ZODPOVEDANÉ V ASOCIÁCII MEDZI ZÁKAZNÍKOM A FAKTÚROU. A O TOM, PREČO PRÁVE TAKTO, NABUDÚCE.

Ďalšie blog posty, čo by ťa mohli zaujímať