Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij slevové akce 50% výuky zdarma!
Pouze tento týden sleva až 80 % na e-learning týkající se Javy

Lekce 5 - UML - Class diagram

V minulé lekci, UML - Doménový model, jsme si vytvořili doménový model a tak jsme si vlastně ukázali základní notaci tříd v UML a také základní vztahy, které mezi sebou třídy mohou mít. Doménový model byl zjednodušenou verzí modelu třídního (Class diagramu). Dnes si ukážeme nějaké další vazby a vytvoříme si třídní diagram.

Class diagram

Diagram tříd je diagram implementace. To je rozdíl oproti doménovému modelu, který byl spíše náčrt systému. Class diagram je již naostro, musí být úplný, když ho programátor přepíše do kódu, kód musí fungovat. Budeme zde mít tedy všechny třídy, které aplikace bude obsahovat. Třídy budou mít všechny atributy a také metody. Diagram je platformově závislý, tedy specifický pro určitý programovací jazyk. Mimo jiné to znamená, že se v identifikátorech již nevyskytuje diakritika, atributy mají datové typy specifické pro daný jazyk a podobně.

Význam diagramu

Class diagram je návod pro programátora, ten by již neměl s naším diagramem řešit žádné zásadní otázky ani problémy, jeho práce by měla být (možná bohužel :) ) rutinní. Návrh systému mají na starosti zkušení programátoři a analytici. Díky návrhu se potom samotné programování může předat i méně zkušeným programátorům, kteří jsou mnohdy levnější. Diagram tříd je dobré vytvořit však i v případě, že systém píšeme jen pro sebe, donutí nás to nejprve přemýšlet v kontextu celého systému a až potom programovat. Nestane se nám, že napíšeme půlku systému a potom zjistíme, že to takhle nebude fungovat. Složitější informační systémy již nelze vytvářet bez návrhu a i práce v týmu se bez kvalitního návrhu neobejde. Diagram nám do budoucnosti poslouží i jako dokumentace.

Ukažme si ještě jednou grafickou notaci třídy v UML, tentokrát již kompletní:

Třída v UML diagramu

V první části obdélníku je opět název třídy, tentokrát již bez diakritiky.

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

V druhé části jsou přítomny atributy s datovými typy. Před každým atributem je uveden modifikátor přístupu. Máme 4 možnosti:

  • - (mínus) - Privátní atribut (private).
  • + (plus) - Veřejný atribut (public).
  • # (hash kříž) - Protected atribut (protected).
  • ~ (tilda) - Atribut viditelný v rámci balíku (package).

Význam prvních 3 určitě známe z objektově orientovaného programování, package atribut je atribut viditelný v rámci celého balíčku tříd (tedy jmenného prostoru).

Mezi název atributu a datový typ píšeme dvojtečku.

Metody v posledním obdélníku jsou zapisovány podobně. Je možné specifikovat ještě několik symbolů, ale to se v praxi příliš nepoužívá a proto se tím nebudeme zabývat.

Vztahy

Oproti doménovému modelu zde můžeme použít ještě další 2 vztahy.

Realizace (Realization)

Vztah realizace je mezi interface a třídou, která tento interface implementuje. Třída reprezentující interface má tzv. stereotyp. Ten se píše do dvojitých špičatých závorek, stejně jako tomu je u vazby <<include>> v Use Case diagramu. Stereotyp umožňuje změnit význam určitého prvku v diagramu, nyní měníme třídu na interface. Třída implementující interface je k interface připojena vazbou podobnou dědičnosti, pouze je čára vykreslena jako přerušovaná.

Realizace interface v UML diagramu

Asociační třída (Association class)

Asociační třída je třída, která zprostředkovává vztah mezi 2 entitami. Výhodou je to, že může vztahu dodat nějaké atributy. Často se uvádí příklad tříd Osoba a Zajezd, kdy asociační třída Ucast přiřazuje osobu na zájezd a dodává čas příjezdu a odjezdu. Dalším příkladem je třeba Osoba a Hotel, kdy v hotelu není pevně stanovený čas ubytování a objednává si ho konkrétní osoba. Podobná třída by mohla ještě např. být mezi zaměstnancem a firmou, kde by definovala plat zaměstnance. Dalším využitím může být možnost takto vytvořit vazbu M:N, podobně, jako to funguje u databází. Asociační třída by tedy držela kolekci referencí. Použití asociační třídy může být poněkud zavádějící a pokud si nejste jistí, tak se ji raději vyhněte.

Asociační třída v UML diagramu

Příklad Class diagramu

Přejděme k příkladu a vytvořme si Class diagram ITnetwork. Budeme samozřejmě vycházet z předešlého doménového modelu.

Předem upozorňuji, že příklad je velmi zjednodušený, návrh není ideální a nectí MVC architekturu, jak je u webových aplikací zvykem.

Příklad class diagramu, diagramu tříd v UML

Vidíme, že oproti doménovému modelu zde máme úplně novou třídu System. Ta drží instance aktuálního článku a aktuálního uživatele. Dále drží kolekce článků, členů a sekcí. Doménový model pouze mapoval důležité entity z hlediska business zadání a tedy ani nepřemýšlel nad tím, jak systém bude uvnitř fungovat. Počet tříd se tedy prakticky vždy s přechodem od doménového modelu k Class diagramu zvýší.

Instance systému se vytváří s každým HTTP požadavkem, jak nám říká poznámka ke třídě nalevo. Za povšimnutí stojí také výčtový typ StavClanku, který je zde zakreslen jako třída a výčtový typ je z něj vytvořen pomocí stereotypu <<enumerable>>. Zbytek jsme si již popsali, takže si diagram prohlédněte. Jako je to u všech diagramů, je to jeden možný způsob, jak systém navrhnout, možností je nespočetně a i těch správných je mnoho.

Příště, v lekci UML - State Machine diagram, se zaměříme na popis tříd a ukážeme si ještě komplexnější praktický příklad Class Diagramu.


 

Předchozí článek
UML - Doménový model
Všechny články v sekci
UML
Článek pro vás napsal David Čápka
Avatar
Jak se ti líbí článek?
20 hlasů
David je zakladatelem ITnetwork a programování se profesionálně věnuje 13 let. Má rád Nirvanu, sushi a svobodu podnikání.
Unicorn university David se informační technologie naučil na Unicorn University - prestižní soukromé vysoké škole IT a ekonomie.
Aktivity (8)

 

 

Komentáře

Avatar
valgard
Člen
Avatar
valgard:5.11.2012 15:33

Ahoj. Na konci článku je napísané, že bude ďalší článok o popise tried a ďalší podrobnější príklad class diagramu. Je to ešte v pláne ? Rád by som sa dozvedel o tejto problematike viac. Inak super seriál. Ďakujem.

 
Odpovědět
5.11.2012 15:33
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na valgard
David Čápka:5.11.2012 15:41

Jo, je v plánu :)

Odpovědět
5.11.2012 15:41
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
Odpovídá na David Čápka
Michael Olšavský:26.2.2013 19:14

Pěkný článek, ale jak se značí statické třídy a metody?

 
Odpovědět
26.2.2013 19:14
Avatar
Drahomír Hanák
Redaktor
Avatar
Odpovídá na Michael Olšavský
Drahomír Hanák:26.2.2013 19:33

Nepoužívej statiku, s DI (resp. IoC) to většinou jde a používá se jen v dobře opodstatněných případech ;) Jinak se v Class diagramu značím myslím '_' (podtržítkem).

 
Odpovědět
26.2.2013 19:33
Avatar
Odpovídá na Drahomír Hanák
Michael Olšavský:26.2.2013 19:37

Ok. Díky za radu. Já ji teď používal pro připojení k sql databázy, jelikož jsem ji potřeboval v několika třídách a zdálo se mi zbytečné neustále předávat objekt databáze v konstruktoru.

 
Odpovědět
26.2.2013 19:37
Avatar
Drahomír Hanák
Redaktor
Avatar
Odpovídá na Michael Olšavský
Drahomír Hanák:26.2.2013 19:54

Ono to právě zbytečné není :) Jakmile se ti aplikace rozroste na několik set nebo tisíce tříd a třeba k tomu ještě děláš v týmu několika lidí, tak oceníš čitelnost a zřetelnost, kterou nabízí Dependency Injection. Ono ani nemusíš dělat v týmu. Bohatě stačí, když se za měsíc nebo za rok podíváš na svůj starý kód. Ze statiky nezjistíš skutečné závislosti objektu (musíš se proklikávat a i tak se dá dost přehlédnout) a tak to může být velký problém (z vlastní zkušenosti) :D Ale je fakt, že ruční implementace je dost zdlouhavá.

 
Odpovědět
26.2.2013 19:54
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Michael Olšavský
David Čápka:26.2.2013 20:22

Statické atributy a metody jsou podtržené. Statiky bych se zas tolik nebál, je na ní založený celý .NET framework a nevšiml jsem si, že by s tím byl někde problém. Spíše je to problém pro začátečníky, že v tom začnou něco prasit.

Odpovědět
26.2.2013 20:22
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
 
Odpovědět
26.2.2013 20:25
Avatar
Kit
Redaktor
Avatar
Odpovídá na Michael Olšavský
Kit:27.2.2013 8:44

Když budeš předávat objekt databáze konstruktoru, výrazně si usnadníš testování. Prostě místo databáze podstrčíš konstruktoru mock, který se bude tvářit jako databáze. Můžeš si tak nasimulovat jakoukoli situaci a nemusíš si přitom mršit ostrá data.

Odpovědět
27.2.2013 8:44
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
 
Odpovědět
27.2.2013 16:11
Avatar
Kit
Redaktor
Avatar
Odpovídá na Michael Olšavský
Kit:27.2.2013 17:15

Chytré to je, ale já to nevymyslel. Je to součástí TDD. Pokud se to dělá důsledně, v aplikaci se to podobnými konstrukcemi jen hemží.

Objekt databáze obvykle předám konstruktoru modelu a objekt modelu pak předám controlleru nebo vieweru, který vyrobím ve factory. Z programu se tak stane skládačka, ve které se dá otestovat každá komponenta zvlášť.

Odpovědět
27.2.2013 17:15
Vlastnosti objektů by neměly být veřejné. A to ani prostřednictvím getterů/setterů.
Avatar
Juraj Mlich
Redaktor
Avatar
Juraj Mlich:1.7.2013 10:31

Ako zapíšem preťaženú metodu?

 
Odpovědět
1.7.2013 10:31
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Drahomír Hanák
Milan Gallas:3.12.2013 19:05

Napsal jsi statiku nepoužívej, ale jak chceš zajistit například jedinečnou instanci nějaké třídy. Při práci v týmu budeš muset nějak zajistit, aby si každý programátor v týmu nemohl vytvořit instancí třídy (která zajišťuje připojení k databázi, nebo nějaké ladící nástroje)? Jednu jedinečnou instanci bez návrhového vzoru Singleton(který využívá principy statiky) neuděláš a pokud znáš způsob jak v tomhle případě statiku obejít, tak mi ho prosím zděl :)

 
Odpovědět
3.12.2013 19:05
Avatar
Drahomír Hanák
Redaktor
Avatar
Odpovídá na Milan Gallas
Drahomír Hanák:3.12.2013 20:10

O to, aby byla instance jedinečná, se mi stará DI kontejner

 
Odpovědět
3.12.2013 20:10
Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Drahomír Hanák
Milan Gallas:3.12.2013 23:12

i to má svůj problém.
pro konkrétní případ si dovolím půjčit tvojí továrnu, kterou máš popsanou v článku http://www.itnetwork.cz/…avrhovy-vzor

Ber v úvahu, že tvoji kolegové ve firmě nebudou vědět, že pro získání objektu můžou zvolit metodu getConnection(), ale vytvoří si novou instanci třídy Container a zavolají znovu metodu createConnecti­on(); Pokud již budeš mít takto vytvořený objekt a některý z tvých kolegů si vytvoří další instanci tak Vytvořené objekty nebudou stejné a bude docházet k plýtvání pamětí.

Kdybych použil Singleton tak použiji privátní konstruktor a přinutím je používat metody getConnection, ale ty je nijak nepřinutíš a oni si můžou vytvořit tolit instancí, kolik budou chtít.

 
Odpovědět
3.12.2013 23:12
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Drahomír Hanák
Milan Gallas:3.12.2013 23:21

a navíc třídu Container si může kdokoli naklonovat a to tvoje třída také vůbec neřeší:

$container = new Container('Localhost', 'test', 'aaabbb', 'myTable');
$db = $container->createConnection();
$db2 = clone $db;

Pokud mi tyhle 2 věci vyvrátíš, tak uznám svou chybu a uznám že jsem se spletl, ale zatím si myslím, že Ten kontejner má své nedostatky a že nedokáže zajistit na 100ˇ%, aby existovala pouze **1 **instance dané třídy.

 
Odpovědět
3.12.2013 23:21
Avatar
Drahomír Hanák
Redaktor
Avatar
Odpovídá na Milan Gallas
Drahomír Hanák:3.12.2013 23:25

Já mám v práci chytré kolegy, kteří znají ten návrhový vzor a ještě chytřejší DIC, který nikomu nedovolí tohle udělat (dokonce umí sám ty závislosti třídám předávat) ;) Paradoxně hlavní problém singletonu je nepřehlednost. Třída si někde magicky z globálního prostoru vezme instanci. Přitom má signaturu třeba class UserDao(); Kde z toho poznám, že potřebuje databázi? A když si podle názvu odvodím, že asi nějakou databázi potřebuje, odkud si ji vezme? A jak ji v testech budu mockovat? Z praxe vím, že Singleton ve větších aplikacích nenahradí DI. Dokonce jsem se setkal s případem, kdy firma měla v jedné aplikaci tohle řešení singletony. Jak na aplikaci dělalo stále víc lidí, muselo se to prostě přepsat.

Nechci to nikomu nutit, mluvím na základě svých zkušeností z pár firem a vlastních projektů. Určitě jsou tu zkušenější uživatelé, kteří ti poradí mnohem lépe.

Mimochodem, tomu zneužití co píšeš, se dá dost jednoduše zamezit.

Editováno 3.12.2013 23:29
 
Odpovědět
3.12.2013 23:25
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Drahomír Hanák
Milan Gallas:3.12.2013 23:31

a jak si to teda v tom svém DIC vyřešil, Aby výše zmíněné věci nebyly možné a DIC to nikomu nedovolilo?
Mě jde o konkrétní postup zamezení těchto 2 "ohavností", které ti můžou tvoji kolegové způsobit.

 
Odpovědět
3.12.2013 23:31
Avatar
Drahomír Hanák
Redaktor
Avatar
Odpovídá na Milan Gallas
Drahomír Hanák:3.12.2013 23:56

K instanci DIC vůbec nemají přístup nebo jen velmi omezený.
V DIC si definuji službu buďto jako service (vytváření instancí je plně pod kontrolou kontejneru tj. createConnection je privátní) nebo jako factory (očekávám, že bude instancí víc, tady předávám tovární funkci) Klonování si např. v PHP ošetříš pomocí vlastní definice __clone().

O tom, že by uživatel vytvořil kontejner nemá cenu diskutovat. Třídy uvnitř systému nikdy nebudou vědět, že nějaký kontejner existuje. Kdyby ho někdo přece jen vytvořil ručně sám (což je velice nepravděpodobné), musel by do něj definovat všechny služby a továrny z celého systému znovu, aby mu to fungovalo.

Ty mi zase řekni, jak mám mockovat singleton v testech? Co když budu chtít přepínat mezi uložišti (databáze/cache)? Co když tam přidám v průběhu vývoje další možnosti? Abys udělal tohle, musel bych nejspíš narušit základní návrhové principy (jako třeba single responsibility, open-closed princip dokonce princip převrácaného předávání závislostí je základním principem). Nebo jak tedy jasně zjistit závislosti třídy? To, že je globální taky není moc ok. Nevýhody singletonu tedy alespoň pro mě jasně převyšují nevýhody DI (můžeme se dál bavit o tom, že si někdo ručně vytvoří tu službu nebo použije reflexi, ale nemá to cenu, protože to se v praxi nestane)

 
Odpovědět
3.12.2013 23:56
Avatar
Drahomír Hanák
Redaktor
Avatar
Odpovídá na Milan Gallas
Drahomír Hanák:4.12.2013 0:08

Abych to ještě uvedl na pravou míru. To, o čem tu diskutujeme, není Dependency Injection, ale Dependency Injection Container (DIC). DI je v zásadě i toto: new UserDao(new Database('local­host')) i když takhle zapsané to není v praxi použitelné.

Ještě bych chtěl možná zmínit, že DI a singleton se navzájem nevylučují.

Editováno 4.12.2013 0:10
 
Odpovědět
4.12.2013 0:08
Avatar
Milan Gallas
Redaktor
Avatar
Odpovídá na Drahomír Hanák
Milan Gallas:4.12.2013 18:02

Tak uznávám, že po menší úpravě kódu by mohla být ochrana dostačující(nikoli 100%). Jednoduchá verze třídy by mohla vypadat třeba takto:
http://www.itnetwork.cz/dev-lighter/253

Editováno 4.12.2013 18:02
 
Odpovědět
4.12.2013 18:02
Avatar
strongmann
Člen
Avatar
strongmann:3.9.2017 20:02

Ahoj,
jen se chci zeptat, privátníAtribut je + (plus), zatímco privátníMetoda je - (mínus)(viz. obecný diagram třídy) není to chyba?
Moje chyba, přehlédl jsem se jak tam jsou přehozené řádky...

Editováno 3.9.2017 20:03
 
Odpovědět
3.9.2017 20:02
Avatar
nickname01
Člen
Avatar
nickname01:21.11.2017 18:01

Lze do class diagramu zakreslit namespace? Pokud ano, jak?

 
Odpovědět
21.11.2017 18:01
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na nickname01
David Čápka:21.11.2017 18:24

K tomu je diagram balíčků, viz dále v kurzu :)

Odpovědět
21.11.2017 18:24
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
nickname01
Člen
Avatar
Odpovídá na David Čápka
nickname01:21.11.2017 18:32

Díky. Takže namespace do class diagramu zakreslit nelze?

Editováno 21.11.2017 18:32
 
Odpovědět
21.11.2017 18:32
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na nickname01
David Čápka:21.11.2017 18:35

Myslím, že by se tam dal zanést pomocí značky pro balíčky, viz dále. Třídy bys potom umístil do symbolu pro balíček. Ale ještě jsem to tak v praxi neviděl.

Odpovědět
21.11.2017 18:35
Jsem moc rád, že jsi na síti, a přeji ti top IT kariéru, ať jako zaměstnanec nebo podnikatel. Máš na to! :)
Avatar
nickname01
Člen
Avatar
Odpovídá na David Čápka
nickname01:21.11.2017 18:38

Díky ;-)

Editováno 21.11.2017 18:39
 
Odpovědět
21.11.2017 18:38
Avatar
Pavel Šaman
Člen
Avatar
Pavel Šaman:14.4.2018 15:16

Dobrý den,
pochopil jsem, že Clanek by si měl uchovávat odkaz na Redaktor, ale nevidím to mezi atributy u třídy Clanek. Jak se toto řeší v kódu? Čekal bych, že třída bude obsahovat atribut Redaktor (instanci třídy Redaktor), tzn. odkaz na redaktora článku. Pak bych to ale čekal i v class diagramu takto zakreslené.
Děkuji za odpověď

 
Odpovědět
14.4.2018 15:16
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 28 zpráv z 28.