Biologie | Chimie | Didactica | Fizica | Geografie | Informatica | |
Istorie | Literatura | Matematica | Psihologie |
Diagrame de clase
Modelarea unui sistem presupune identificarea lucrurilor care sunt importante pentru acesta si care formeaza vocabularul sistemului. In UML, toate aceste lucruri sunt modelate folosind clase.
O clasa inseamna descrierea unei multimi de obiecte care au in comun aceleasi atribute, operatii, relatii si semnificatie.
Diagramele de clase sunt folosite pentru a specifica structura statica a sistemului, adica ce clase exista in sistem si care este legatura dintre ele.
In UML, o clasa este prezentata ca un dreptunghi in interiorul caruia se scrie numele acesteia.
Fiecare clasa este caracterizata printr-o multime de operatii si atribute.
Atribute
Un atribut reprezinta o proprietate a unei clase.
Atributele descriu datele continute de obiectele din clasa respectiva
Pentru fiecare atribut trebuie specificat tipul acestuia. Tipurile folosite pot fi tipuri de baza sau clase.
Pentru fiecare atribut pot fi specificate vizibilitatea, multiplicitatea si valoarea initiala.
Din punct de vedere al vizibilitatii, atributele pot fi publice, private sau protejate, marcate cu '+', '-' si respectiv '#':
atribute publice: pot fi accesate de orice alta clasa
atribute private: pot fi accesate de alte clase
atribute protejate: pot fi accesate doar de subclasele care descind din clasa respectiva
In principiu, este bine ca, in masura in care este posibil, atributele sa fie declarate private, conform principiului incapsularii.
Operatii
Operatiile clasei definesc modurile in care interactioneaza obiectele.
Cand un obiect trimite un mesaj catre un alt obiect, ii cere acestuia din urma sa execute o operatie.
Obiectul care primeste mesajul va apela o metoda pentru a executa aceasta operatie.
Metoda reprezinta implementarea operatiei si defineste comportamentul acesteia.
Obiectul care a trimis mesajul nu trebuie sa cunoasca ce metoda a fost apelata.
De exemplu, folosind limbajul Java, daca un mesaj este trimis unui obiect abonat din clasa Abonat,
abonat.imprumuta(copie)
atunci clasa Abonat va trebui sa aiba o metoda impumutat
public void impumutat ()
Semnatura unei operatii este formata din numele sau, numele si tipurile parametrilor formali precum si tipul care trebuie returnat, daca este cazul.
Operatii specifice sunt:
constructorii
accesorii (getX)
mutatorii (setX)
La fel ca si atributele, operatiile pot fi publice, private sau protejate.
Daca operatia este publica atunci mesajul poate fi trimis de orice obiect.
Daca operatia este privata atunci mesajul poate fi trimis doar de un obiect din clasa respectiva (care contine operatia).
Daca operatia este protejata, mesajul va putea fi trimis doar din obiecte apartinand subclaselor descendente din clasa care contine operatia.
In diagrama de clase, intre atributele unei clase nu sunt incluse atribute care doar implementeaza asociatiile dintre clase. In implementarea finala va exista un astfel de atribut, dar nu este necesar ca acest lucru sa apara in aceasta faza si ar incarca prea mult diagrama de clase.
Relatii
Clasele formeaza relatii. Tipuri de relatii intre clase:
asociere
generalizare
dependenta
realizare
Asocierile sunt legaturi structurale intre clase.
Intre doua clase exista o asociere atunci cand un obiect ditr-o clasa interactioneaza un obiect din cealalta clasa.
Dupa cum clasele erau reprezentate prin substantive, asocierile sunt reprezentate prin verbe.
Pentru a indica directia de citire a numelui asocierii (de exemplu de la Abonat la CopieCarte) se poate folosi un triunghi negru.
In general, clasa A este asociata cu clasa B, daca un obiect din clasa A trebuie sa aiba cunostinta de un obiect din clasa B. Mai in detaliu putem identifica urmatoarele cazuri:
Un obiect din clasa A trimite un mesaj catre un obiect din clasa B;
Un obiect din clasa A creeaza un obiect din clasa B;
Un obiect din clasa A are un atribut ale carui valori sunt obiecte sau colectii de obiecte din clasa B.
Participarea unei clase la o asociere este caracterizata de o anumita multiplicitate. De exemplu, o carte poate avea una sau mai multe copii, in timp ce o copie carte poate apartine numai unei singure carti.
In UML, multiplicitatile pot fi specificate in modul urmator:
Un numar, de exemplu 1
Un interval de numere, de exemplu 2..5
Un numar arbitrar, folosind simbolul *.
Enumerarea mai multor posibilitati, de exemplu 1,10..20,100..*
Uneori asocierea este mai usor de inteles daca rolurilor pe care obiectele le au in cadrul asocierii li se atribuie nume separate.
In UML putem plasa o sageata la unul dintre capetele liniei ce reprezinta asocierea pentru a arata ca este posibil sa se trimita mesaje in directia sagetii.
Spunem ca obiectul Curs va avea cunostinta de obiectul Student, dar nu si invers.
Specificarea unei directii de navigatie nu inseamna neaparat ca nu este posibila o navigatie in sens invers, ci ca acest lucru este mai greu de realizat.
Atunci cand se specifica sensul de navigare de la o clasa A la o clasa B inseamna ca exista o modalitate precisa si directa de acces de la un obiect din clasa A la un obiect din clasa B (A stocheaza o referinta la B).
In exemplul de fata, o astfel de asociere poate fi implementata printr-un atribut care sa reprezinte multimea de obiecte din clasa Student care participa la Curs.
Daca nu exista nici o sageata (navigabilitatea nu este specificata explicit) atunci se considera ca ascierea este bidirectionala.
In general, navigabilitatea nu este specificata explicit decat daca este cu adevarat importanta pentru aplicatie.
Agregarea si compunerea reprezinta tipuri de asociere in care un obiect dintr-o clasa face parte dintr-un obiect din alta clasa.
Agregarea este modul cel mai general de a indica in UML o relatie de tip parte-intreg,
Diferenta dintre o simpa asociere si agregarea este pur conceptuala: folosirea agregarii indica faptul ca o clasa reprezinta un lucru 'mai mare' (intregul), care contine mai multe lucruri 'mai mici' (partile).
Exista insa un caz special de agregare, compunerea, in care relatia dintre intreg si partile sale este mai puternica.
O asociere de tip compunere implica o apartenenta puternica a partii la intreg si o coincidenta intre durata de viata a partii si intregului: daca intregul este creat, mutat sau distrus, atunci si partile componente sunt create mutate sau distruse.
In cazul compunerii, o parte nu poate sa fie continuta in mai mult de un singur intreg, astfel incat multiplicitatea asocierii la extremitatea intregului trebuie sa fie 1 sau 0..1.
Asocieri a caror existenta poate fi dedusa din existenta altor asocieri ale diagramei.
De cele mai multe ori, reprezentarea explicita a unei asocieri derivate nu este necesara
Doua sau mai multe asocieri care nu pot exista in acelasi timp, cu alte cuvinte exista un "sau exclusiv" intre acestea.
asociere poate avea date si responsabilitati proprii; de exemplu nota studentului la curs.
astfel de asociere poate fi tratata ea insasi ca o clasa.
Relatie intre un lucru general (numit super-clasa sau parinte, ex. Abonat) si un lucru mai specializat (numit sub-clasa sau copil, ex. AbonatPremium)
Un obiect al unei clase mai generale, poate fi substituit cu un obiect al unei clase mai specializate in orice context, dar nu si invers.
Intr-o relatie de generalizare, copilul va mosteni structura si comportamentul parintelui: toate atributele, operatiile si relatiile care exista in super-clasa vor exista si in sub-clasa.
Pe de alta parte, copilul poate adauga structura si comportament nou, adica poate avea atribute, operatii si relatii noi fata de cele ale superclasei.
In plus, copilul poate chiar schimba comportamentul parintelui. Acest lucru se intampla atunci cand o operatie a sub-clasei care are aceeasi semnatura ca o operatie a super-clasei suprascrie acea operatie. Acest lucru poarta numele de polimorfism.
Generalizarea se foloseste adesea pentru a pune in evidenta similaritatile dintre mai multe clase. De exemplu, CopieCarte si CopieCaseta
Atunci cand o clasa care are un singur parinte se spune ca foloseste mostenire simpla, in caz contrar mostenirea se numeste multipla. In majoritatea cazurilor mostenirea simpla este suficienta, dar exista insa si cazuri cand mostenirea multimpla este mai eficienta.
Mostenirea multipla poate fi problematica daca un copil are mai multi parinti a caror comportament se suprapune. In multe cazuri, mostenirea multipla poate fi inlocuita de agregare si mostenire simpla: copilul mosteneste de la un singur parinte, care este obtinut prin agregarea mai multor parinti.
O clasa abstracta este o clasa pentru care nu pot exista instante directe.
O clasa abstracta nu furnizeaza implementarea pentru cel putin una dintre operatiile sale.
O clasa concreta este una care poate avea instante directe.
In UML numele unei clase abstracte se scrie in italic
Clasele abstracte pot fi folosite ca superclase intr-o ierarhie de clase intre care exista o asociere de tip generalizare. O astfel de ierarhie va avea ca nod radacina o clasa abstracta, iar ca noduri frunze clase concrete.
Utilitatea claselor abstracte (exemplu in Java)
Figura triunghi = new Triunghi();
Figura linie = new Linie();
/** Presupunem ca avem doua obiecte din clasa Figura, unul fiind un triunghi, iar celalat o linie. */
/** Daca Figura nu ar fi clasa abstracta, atunci operatia deseneaza nu poate fi declarata la nivelul acestei clase si deci nu putem folosi aceasta metoda pentru obiectele triunghi sau linie */
triunghi.deseneaza();
linie.deseneaza();
Daca insa metoda deseneaza este declarata in superclasa Figura ca metoda abstracta, atunci acest lucru este posibil, in fiecare caz apelandu-se prin intermediul superclasei Figura implementarea respectiva (pentru triunghi sau linie. Cu alte cuvinte mesajele catre obiectele din subclase se trimit prin intermediul superclasei */
/** Daca o clasa este declarata abstracta, atunci nu este posibila folosirea constructorului acelei subclase (ea nu poate avea instante directe) */
Figura figura = new Figura();
O clasa A depinde de o clasa B daca o modificare in specificatia lui B poate produce modificarea lui A, dar nu neaparat si viceversa.
Cel mai frecvent caz de dependenta este relatia dintre o clasa care foloseste alta clasa ca parametru la o operatie.
In UML, o interfata specifica o colectie de operatii pe care trebuie sa le furnizeze o clasa sau o componenta.
Interfata nu cuprinde implementarile acestor operatii si nici nu face nici o referire la starea obiectului care corespunde acestei interfete. Cu alte cuvinte, interfata nu are atribute.
Interfata specifica operatiile unui element, de exemplu o clasa, care sunt vizibile in afara acestuia. Ea nu trebuie sa specifice toate operatiile pe care le poate efectua acel element, astfel incat acelasi element poate corespunde mai multor interfete iar o interfata poate corespunde mai multor elemente.
O interfata este definita intr-o diagrama de clase printr-un dreptunghi, avand operatiile listate in compartimentul de jos, la fel ca la o clasa; spre deosebire de o clasa, o interfata nu poate avea atribute si in consecinta nu va avea un compartiment pentru acestea. In primul compartiment, deasupra numelui clasei, va aparea stereotipul « interface ».
Exemplu: clasa Producator si interfata acesteia, Livrare. Clasa Distribuitor depinde de interfata Livrare (sageata de dependenta).
Vom spune ca Producator este o clasa ce corespunde sau realizeaza interfata Livrare. Acest lucru se reprezinta in doua feluri:
printr-o linie punctata cu o sageata triunghiulara de la Producator la Livrare.
printr-un cerc cu eticheta Livrare, atasat dreptunghiului ce reprezinta clasa Producator.
Realizarea unei interfete poate fi privita ca un fel de mostenire:
Clasa Producator furnizeaza cel putin toate operatiile furnizate de interfata Livrare si poate furniza si operatii suplimentare.
Doar specificatia operatiei este mostenita: clasa Producator trebuie sa furnizeze singura implementarile acestei operatii, deoarece interfata nu poate contine implementari.
Interfata sau generalizare (clasa abstracta)?
Conceptual: Interfata nu presupune o relatie stransa intre clase precum generalizarea.
Atunci cand se intentioneaza crearea unor de clase inrudite. care au comportament comun, atunci trebuie folosita generalizarea.
Daca se vrea doar o multime de obiecte care sunct calabile sa efectueze niste operatii comune (afisare, etc.), atunci interfata este de preferat.
Implementare: Anumite limbaje (Java) ofera doar mostenire simpla, astfel incat interfata este in acest caz singura solutie pentru implementarea mostenirii multiple. O clasa poate mosteni de la o singura superclasa, dar poate implementa mai multe interfete.
O clasa parametrizata nu este o clasa propriu-zisa, ci o functie care ia ca parametru o clasa si returneaza o clasa.
O clasa parametrizata se reprezinta la fel ca o clasa obisnuita la care se adauga in dreapta sus un dreptunghi punctat in care apare numele parametrului formal.
Lista<C> denumeste clasa care rezulta prin aplicarea clase parametrizate: o lista de obiecte din clasa C
Toate clasele care rezulta prin aplicarea unei clase parametrizate vor depinde de acea clasa
Stereotipul « bind » care eticheteaza dependenta dintre clasa parametrizata si clasa rezultat arata ca aceasta din urma este obtinuta prin instantierea clasei parametrizate cu parametrul efectiv specificat (Student sau Curs)
Folosirea clasei parametrizate duce la refolosirea ei la definirea ambelor clase (Student si Curs).
In general, clasele pot proveni din doua surse principale:
Lucruri concrete: carte, caseta, copie, curs;
Roluri: abonat, profesor, student.
Principii de design
Clasele trebuie sa fie bine delimitate, iar gradul de dependenta dintre ele sa fie cat mai redus; o clasa trebuie sa prezinte un grad mare de coeziune interna si unul redus de interactiune externa.
Clasele trebuie alese in asa fel incat mentinerea, extinderea si adaptarea lor la noi cerinte sa se poata face cu usurinta. Un model bun este acela in care clasele reprezinta obiecte stabile in timp care nu sunt dependente de functionalitatea curenta si care vor fi pastrate si dupa modificarea functionalitatii sistemului.
Strategii de identificare a claselor
conduse de date (data driven): pune accent pe identificarea tuturor datelor din sistem si impartirea lor in clase (ex. tehnica identificarii substantivelor)
conduse de responsabilitati (responsibility driven): pune accent pe identificarea tuturor responsabilitatilor si impartirea lor in clase (ex. tehnica cardurilor CRC)
Proces de identificare al claselor:
are caracter iterativ
se poate incepe cu tehnica identificarii substantivelor pentru identificarea claselor candidate
modelul poate fi apoi rafinat folosind metoda cardurilor CRC
Tehnica identificarii substantivelor
Identificarea claselor candidate, prin selectarea substantivelor si a constructiilor cu rol de substantiv din cerintele sistemului;
Eliminarea claselor candidate care sunt inadecvate dintr-un motiv sau altul.
Motivele pentru care o clasa candidata poate fi inadecvata pot fi:
In afara scopului sistemului, atunci cand substantivul are legatura cu modul in care functioneaza sistemul, dar nu se refera la o parte a acestuia. Aceasta regula este deseori folosita pentru a elimina actorii, atunci cand nu este necesara modelarea lor in cadrul sistemului;
Meta-limbaj, atunci cand substantivul este folosit la definirea unor lucruri (de exemplu, cuvinte precum sistem sau cerinte);
Redundanta, atunci cand aceleiasi clase ii sunt atribuite mai multe nume.
Un eveniment sau o operatie, atunci cand substantivul se refera la ceva ce este efectuat de catre sau asupra sistemului. Criteriul care poate fi aplicat in acest caz este de a vedea daca evenimentul sau operatia in cauza are stare. In caz contrar, acesta trebuie eliminat;
Cuvant ambiguu, a carui semnificatie trebuie clarificata inainte de a decide daca reprezinta sau nu o clasa;
Atribut, atunci cand este clar ca substantivul se refera la ceva simplu, care nu are comportament de sine statator, fiind de fapt un atribut al unei clase.
Se obtine astfel un model al claselor de nivel inalt (conceptual). Acest model este apoi rafinat in timp.
O modalitate uzuala de a verifica un design bun si de a-l rafina este tehnica carduri CRC (Class, Responsibilities, Collaboration).
Pe o bucata de hartie de dimensiunea unei carti de vizita, se scriu:
Numele clasei, in partea de sus (ca titlu);
Responsabilitatile clasei, in partea stanga;
Colaboratorii clasei, care contribuie la indeplinirea responsabilitatilor, in partea din dreapta.
Responsabilitatile clasei descriu la un nivel inalt scopul pentru care exista clasa. Ele au legatura cu operatiile furnizate de clasa, dar au un caracter mai general decat acestea.
O clasa nu trebuie sa aiba in mod normal mai mult de 3-4 responsabilitati, iar majoritatea vor avea 1 sau 2. Daca acest lucru nu se intampla, trebuie investigat daca este posibila reunirea mai multor responsabilitati intr-una singura, iar in caz contrar clasa ar trebui impartita in doua sau mai multe clase. Un numar prea mare de responsabilitati duce la o coeziune prea scazuta a modelului, iar un numar prea scazut la o coeziune prea ridicata. Prin folosirea acestei tehnici pot fi inlaturate ambele extreme.
Folosirea cardurilor CRC usureaza gasirea colaboratorilor unei clase. Daca un obiect dintr-o clasa colaboreaza cu un obiect din alta clasa, acest lucru se face prin transmiterea unui mesaj. Cu alte cuvinte, o clasa este asociata cu fiecare dintre colaboratorii sai, navigabilitatea asocierii fiind in directia transmiterii mesajului. Datorita acestui lucru, tehnica cardurilor CRC permite si determinarea sensului de navigatie a asocierilor.
Fiecare operatie pe care o va executa un obiect va face parte dintr-una din responsabilitatile clasei careia ii apartine obiectul respectiv; responsabilitatile clasei pot fi percepute ca un rezumat al operatiilor pe care aceasta le poate executa. Din acest motiv, pentru verificarea si detalierea modelului se pot imagina scenarii ce corespund diferitelor cazuri de utilizare si pentru fiecare scenariu se verifica daca acesta poate fi realizat folosindu-se responsabilitatile claselor. Acest lucru va incepe de la cardul ce reprezinta clasa intre a carei resposabilitati se numara declansarea scenariului respectiv (un obiect din acea clasa primeste un mesaj de la initiatorul scenariului). Daca obiectul respectiv va apela la un alt card, acest lucru va avea corespondenta in realitate cu un mesaj trimis de acel obiect unui obiect din cealalta clasa. Daca responsabilitatile cerute nu pot fi satisfacute de un obiect, atunci definitia sa va trebui extinsa sau va trebui adaugata colaborarea cu o clasa care poate indeplini aceste resposabilitati.
O modalitate alternativa este de a aranja cardurile astfel incat sa reprezinte relatiile dintre ele, ajungandu-se astfel la o schita a diagramei de clase.
Exemplu: centrul de inchirieri carti si casete
Abonat |
|
Responsabilitati |
Colaboratori |
Imprumuta si returneaza copii ale cartilor |
CopieCarte |
Retine date asupra copiilor imprumutate |
AbonatPremium |
|
Responsabilitati |
Colaboratori |
Imprumuta si returneaza copii ale cartilor si casetelor |
CopieCarte |
Retine date asupra copiilor imprumutate |
CopieCaseta |
Carte |
|
Responsabilitati |
Colaboratori |
Retine numarul de copii ale cartilor imprumutate si disponibile |
CopieCarte |
|
Responsabilitati |
Colaboratori |
Informeaza cartea atunci cand este imprumutata sau returnata |
Carte |
Caseta |
|
Responsabilitati |
Colaboratori |
Retine numarul de copii ale casetei imprumutate si disponibile |
CopieCaseta |
|
Responsabilitati |
Colaboratori |
Informeaza caseta atunci cand este imprumutata sau returnata |
Caseta |
Copyright © 2024 - Toate drepturile rezervate