890 likes | 1.12k Views
Βασικά διαγράμματα σε UML. Ανάπτυξη Λογισμικού ( Software Development ) www.cs.uoi.gr/~pvassil/courses/sw_dev/ ΠΛΥ 308. Δομή. Περί διαγραμμάτων και σχεδίασης λογισμικού Στατικά Διαγράμματα Κλάσεων Δυναμικά Διαγράμματα Ακολουθιών
E N D
Βασικά διαγράμματα σε UML Ανάπτυξη Λογισμικού (Software Development) www.cs.uoi.gr/~pvassil/courses/sw_dev/ ΠΛΥ 308
Δομή • Περί διαγραμμάτων και σχεδίασης λογισμικού • Στατικά Διαγράμματα Κλάσεων • Δυναμικά Διαγράμματα Ακολουθιών Πολλές ευχαριστίες στον Α. Ζάρρα για μια πρώτη μορφή των διαφανειών αυτών
Διαγράμματα • Όπως σε όλες τις επιστήμες των μηχανικών, έτσι και στη μηχανική της σχεδίασης του λογισμικού, κατασκευάζουμε ένα σχέδιο του προς εκτέλεση συστήματος • Όπως σε όλες τις επιστήμες των μηχανικών, έτσι και στη μηχανική της σχεδίασης του λογισμικού, το εν λόγω σχέδιο γίνεται σε μεγάλο βαθμό διαγραμματικά
Διαγράμματα • Η Unified Modeling Language (UML) είναι η γλώσσα που μας προσφέρει τα building blocks με τα οποία κατασκευάζουμε τα διαγράμματα αυτά • Η UML είναι ευρύτατα διαδεδομένη και είναι η γλώσσα προτυποποίησης της σχεδίασης που χρησιμοποιείται παντού • Όταν δεν ακολουθούνται εναλλακτικές μορφές διεκπεραίωσης της ανάπτυξης (τις οποίες θα συναντήσετε στο μάθημα της Τεχν. Λογισμικού)
Γιατί διαγράμματα? • Για μας! • Για να αποτυπώσουμε γρήγορα και κατανοητά το σχέδιο του τι θα υλοποιήσουμε • Για να μπορούμε να κατανοήσουμε τη δομή ενός λογισμικού που πρέπει να συντηρήσουμε • Για να κρύψουμε γενικά την πολυπλοκότητα του κώδικα σε μια φιλική, διαγραμματική και γρήγορα αντιληπτή αποτύπωση που λειτουργεί ως blueprint / σκελετός / σχέδιο της υλοποίησης!
Γιατί διαγράμματα • Για τους άλλους! • Για να μπορούμε, σε ένα συνεργατικό περιβάλλον, να συνεργαστούμε με άλλους, να κατανοούμε όλοι γρήγορα, εύκολα και με ακρίβεια τι έχει / πρόκειτα να υλοποιηθεί από τους άλλους
Μην ξεχνάτε • Τα διαγράμματα τα ζωγραφίζουμε με άπλα στο χώρο, χωρίς οπτικό θόρυβο, και με ακρίβεια (που συνεπάγεται ενημέρωση όταν γίνονται αλλαγές) • ΜΗΝ ΞΕΧΝΑΤΕ: ο σκοπός των διαγραμμάτων είναι να υποβοηθήσουν την κατανόηση του κώδικα και τη συνεργασία των developers (αλλιώς είναι απλώς επιπλέον φόρτος)
(Class diagrams) Διαγραμματα κλασεων
Classes • Class (package, if abstract, …) • Private compartments • Public compartment • Annotate: • Class if abstract • Method if constructor, abstract, … • Method signature • Attribute type
Classes package simpleBookstoreDemo; public class Item { public Item(){title="";price=-1.0;} public Item(String aTitle, double aPrice){title = aTitle; price=aPrice;} public void showDetails() { System.out.println(title + "\t\t Price:" + price);} public double getPrice() {return price;} public double getFinalPrice() {return price;} protected String title; protected double price; }
Comment Notes are used (with restraint) to comment on key points of the SW structure With dashed lines, if they pertain to a specific construct, e.g., a class
Σχέση εξάρτησης (dependency) Dependent typically depends upon DependedUpon for class def., method invocation and stability Η σχέση εξάρτησης καταγράφει ότι ο εξαρτώμενος χρησιμοποιεί κώδικα της εξαρτώντος Αν αλλάξει ο εξαρτών, ίσως πρέπει να αλλάξει και ο εξαρτημένος
Σχέση εξάρτησης (dependency) • Class DC (DependentClass) depends upon class DUC (DependedUponClass) if even one of the following holds: • There exists a method DC.f that takes as parameter an object of DCU DC.f(DUC x): … • There exists a method DC.f that returns an object of DUC DC.f(…): DUC • There exists a method DC.f that uses an object of DUC as an internally declared variable
Παράδειγμα public class SimpleBookstoreEngine { public static void main(String args[]){ ItemManageramazon = new ItemManager(); BookbookRef; bookRef = new Book("Discours de la methode", "Rene Descartes", 1637, 50.00, 0); amazon.addItem(bookRef); bookRef = new Book("The Meditations", "Marcus Aurelius", 180, 30.00, 1); amazon.addItem(bookRef); amazon.reportAllItems(); } }
UML Class Diagrams – Συσχέτιση • Μια απλή σχέση συσχέτισης(Association) σημαίνει ότι κατά τη διάρκεια εκτέλεσης κάποια αντικείμενα των δύο κλάσεων συνυπάρχουν και συνεργάζονται • Hκατεύθυνση (αν υπάρχει) υποδηλώνει ότι αντικείμενα της A_Classγνωρίζουν την ύπαρξη και έχουν τη δυνατότητα πρόσβασηςστα αντικείμενα της Another_Class • Tο multiplicity(αν υπάρχει) δηλώνει ένα εύρος επιτρεπόμενων τιμών σχετικών με το πόσα αντικείμενα συνεργάζονται • 5, 10, 0..1, 1..10, 1..*, 0..*, κλπ. • Yπάρχει επίσης δυνατότητα να ονοματίσουμε το ρόλο που παίζουν τα αντικείμενα κάθε κλάσης στη συνεργασία
Παράδειγμα public class ItemManager { private ArrayList<Item> allItems; … } • Εδώ, κάθε αντικείμενο της κλάσης ItemManagerσυσχετίζεται με μια συλλογή από αντικείμενα της Item
Συσχέτιση vsΕξάρτηση • Η εξάρτηση είναι υποχρεωτικά κατευθυνόμενη • Στη συσχέτιση μπορεί να μην υπάρχει κατεύθυνση, στην περίπτωση αυτή θεωρείται ακαθόριστη • Η εξάρτηση υποδηλώνει ότι μια κλάση εξαρτάται από μια άλλη, χωρίς απαραίτητα η εξάρτηση αυτή να συνεπάγεται την συνύπαρξη και συνεργασία αντικειμένων των δύο κλάσεων. • π.χ. μπορεί μια βοηθητική κλάση Α να προσφέρει μια στατική μέθοδο η οποία καλείται από αντικείμενα μιας άλλης κλάσης Β, απευθείας πάνω στην κλάση Α και όχι πάνω σε ένα αντικείμενο της Α.
Συσχέτιση vsΕξάρτηση class X { public static void doSomething(){ System.out.println("Did something"); } } class Y { public static void doSomethingElse(){ X.doSomething(); System.out.println("Did something else"); } } public class Main { public static void main(String[] args) { Y.doSomethingElse(); } }
Κληρονομικότητα • Για καλύτερη οργάνωση και συντήρηση του κώδικα (για να μην επαναλαμβάνεται ο ίδιος κώδικας πολλές φορές) • φτιάχνουμε μια γενική/βασική κλάση που να περιλαμβάνει τα κοινά χαρακτηριστικά/πεδία και μεθόδους δύο ή περισσοτέρων κλάσεων και • εν συνεχεία επεκτείνουμετη βασική φτιάχνοντας κλάσεις που κληρονομούναπό αυτή. • Στις παραγόμενες κλάσεις δηλώνουμε επιπλέον χαρακτηριστικά και λειτουργίες. • Τα αντικείμενα έχουν όλα τα χαρακτηριστικά και λειτουργίες που δηλώνονται στην βασική κλάση, • καθώς και τα επιπλέον χαρακτηριστικά και λειτουργίες που δηλώνονται στην παραγόμενη κλάση
Κληρονομικότητα & UML • Τα αντικείμενα των παραγόμενων κλάσεων είναι και αντικείμενα της βασικής κλάσης , οπότε η επέκταση ονομάζεται και σχέση IS_A («είναι»). • Η κληρονομικότητα συμβολίζεται με τρίγωνοπου τοποθετείται με την κορυφή να δείχνει προς την αρχική κλάση και τη βάση προς τις παραγόμενες • Εκτός εξαιρετικού απροόπτου, η μητρική κλάση ζωγραφίζεται ψηλά και οι παραγόμενες από κάτω
package simpleBookstoreDemo; • public class Item { ... } • public class Book extends Item { ... } • public class CD extends Item { ... } • public class ItemManager { • private ArrayList<Item> allItems; • ... • }
Στατική Άποψη – Αφηρημένες κλάσεις / Πολυμορφισμός
Γιατί πολυμορφισμός? • Γενικά είναι επιθυμητό είναι να έχουμε τη δυνατότητα να προσθέτουμε νέες δυνατότητες σε ένα πρόγραμμα χωρίς να χρειαστεί να αλλάξουμε δραστικάτονυπάρχοντα κώδικα … • Πώς γίνεται αυτό ?? • συνδυάζουμε κληρονομικότητα & πολυμορφισμό (και για την ακρίβεια: επαναορισμό μεθόδων) • method overriding (επαναορισμός μεθόδων) • η μέθοδος μιας βασική κλάσης ορίζεται ξανά στην παραγόμενη κλάση με νέα υλοποίηση και το ίδιο πρωτότυπο • με αυτή τη τεχνική μπορούμε να πετύχουμε τον επεκτασιμότητα του κώδικα!!
Κληρονομικότητα & Πολυμορφισμός Πώς μπορούμε να ελαχιστοποιήσουμε τη συντήρηση του κώδικα μέσω του πολυμορφισμού? • για κάθε αρμοδιότητα του προγράμματος για την οποία υπάρχει δυνατότητα διαφορετικών εναλλακτικών υλοποιήσεων (πχ διαφορετικές μορφές αποθήκευσης των δεδομένων σε ένα αρχείο) και κατά συνέπεια η δυνατότητα μελλοντικών επεκτάσεων στο πρόγραμμά μας με μια νέα επιπλέον υλοποίηση,ορίζουμε μια βασική κλάση • εν συνεχεία για κάθε διαφορετική εναλλακτική κατασκευάζουμε μια παραγόμενη κλάση η οποία ξανα-ορίζει (overrides) τις public μεθόδους της βασικής κλάσης • υλοποιούμε / παραμετροποιούμε τον υπόλοιπο κώδικα χρησιμοποιώντας αναφορές στη βασική κλάση • οι αναφορές αυτές μπορούν να δείχνουν σε αντικείμενα οποιασδήποτε κλάσης προκύπτει από τη βασική • επομένως τα μόνα σημεία τα οποία πρέπει να αλλαχθούν σε μια μελλοντική επέκταση είναι τα σημεία στο οποία αρχικοποιούνται οι αναφορές αυτές • ο υπόλοιπος κώδικας στον οποίο καλούνται μέθοδοι σε αντικείμενα στα οποία δείχνουν οι αναφορές αυτές δεν χρειάζεται αλλαγές
Αφηρημένες κλάσεις • Δηλώνοντας μια κλάση ως αφηρημένη (abstract) • μια κλάση ονομάζεται αφηρημένη αν περιέχει τουλάχιστον μια αφηρημένη μέθοδο που δεν περιλαμβάνει υλοποίηση • Η κλάση δηλώνεται public abstract class MyAbstractClass • με τη μέθοδο public abstractreturnTypemethodName(); • η αφηρημένη κλάση λειτουργεί σαν καλούπι για την κατασκευή παραγόμενων που προσφέρουν εναλλακτικές υλοποιήσεις στις αφηρημένες μεθόδους…. • η δημιουργία αντικειμένων αφηρημένης κλάσης δεν επιτρέπεται από τον compiler • η μη υλοποίηση αφηρημένων μεθόδων δεν επιτρέπεται από τον compiler
Abstract class package elaborateBookstore; public abstractclass Item { public Item(){title="";price=-1.0;} public Item(String aTitle, double aPrice){ title = aTitle; price=aPrice;} public void showDetails() { System.out.println(title + "\t\t Price:" + price);} public double getPrice(){return price;} public abstract double getFinalPrice(); protected String title; protected double price; }
One implementation package elaborateBookstore; public class Book extends Item { private String author; … @Override public double getFinalPrice() { return price; } }
Another implementation public class CD extends Item { private String artist; … @Override //implem. abstract public double getFinalPrice() { return (price - discount); } public void showDetails() { //override mama class’ method super.showDetails(); System.out.println("by " + artist); System.out.println(“Price f.: “+ getFinalPrice()+ "\n"); } }
Abstract coupling public class ItemManager { private ArrayList<Item> allItems; … } The “client” class ItemManager uses ONLY the abstract class and is completely agnostic to any subclasses the abstract class has. => Zero maintenance cost when new subclasses appear
UML Class Diagrams - Συνάθροιση • Ένα αντικείμενο της κλάσης B_Class (πχ το προφίλ ενός ανθρώπου) είναι συνάθροιση αντικειμένων της C_Classαν χαρακτηρίζεται/αποτελείται από αντικείμενα της κλάσης C_Class (πχ μια διεύθυνση) • Σε μια σχέση συνάθροισης ένα αντικείμενο της κλάσης C_Class (πχ η ίδια διεύθυνση) μπορεί να χαρακτηρίζει πολλαπλά αντικείμενατης κλάσης B_Class (πχ περισσότερα από ένα προφίλ ανθρώπων που μένουν στο ίδιο σπίτι) - Ή αντικείμενα (πχ κτίρια) μιας άλλης κλάσης Ζ_Class… • Σύμφωνα με τα παραπάνω η ύπαρξη των αντικειμένων της C_Classδεν εξαρτάται άμεσα από την ύπαρξη των αντικειμένων της B_Class • (πχ το πρόγραμμα διαχειρίζεται μια λίστα από διευθύνσεις ακόμα και αν δεν υπάρχουν άνθρωποι που μένουν σε αυτές)
Παράδειγμα public class ItemManager { private ArrayList<Item> allItems; … } • Προσοχή στον άσπρο ρόμβο: • Στη μεριά του σύνθετου αντικειμένου • Προσοχή στο χρώμα: άσπρος
Η συνάθροιση είναι μια ειδική περίπτωση συσχέτισης
UML Class Diagrams - Σύνθεση • Ένα αντικείμενο της κλάσης B_Class (πχ μια οικογένεια) αποτελεί σύνθεση αντικειμένων της C_Classαν χαρακτηρίζεται/αποτελείται από αντικείμενα της κλάσης C_Class (πχ μέλη οικογένειας) • Σε μια σχέση σύνθεσης ένα αντικείμενο C_Classανήκει το πολύ σε ένα αντικείμενο της B_Class • Σύμφωνα με τα παραπάνω ένα αντικείμενο της κλάσης C_Class δεν έχει λόγο ύπαρξης αν δεν υπάρχει το αντικείμενο της B_Class το οποίο χαρακτηρίζει
UML Class Diagrams - Σύνθεση • Σε ότι αφορά τη σημειογραφία προσέξτε ότι εδώ το διαμαντάκι είναι μαυρισμένο (σε αντιδιαστολή με το διαμαντάκι της συνάθροισης που είναι άσπρο)
Παράδειγμα class Member{ private String fname; private int age; private int gender; public Member(String fn, int a, int g){ fname = fn; age = a; gender = g; } public int getAge(){ return age; } };
Παράδειγμα classFamily{ privateStringlname; privateintnextChild; private Member father;private Member mother; privateMemberchildren[]; privateMembercreateMember(String n, intage, intgd){ if((age >= 0) && (gd >= 1) && (gd <= 2)) returnnewMember(n, age, gd); else { System.out.println("ErrorinMembercreation !"); returnnull; } } publicFamily(Stringln, intmaxChildren) { lname = ln; if(maxChildren > 0) children = newMember [maxChildren]; } publicvoidsetFather (String n, intage, intgd){ father = createMember(n, age, gd); } …………………………… };
Παράδειγμα class Family{ …………………………………………… public void setMother(String n, int age, int gd){ mother = createMember(n, age, gd); } public void addChild(String n, int age, int gd){ children[nextChild++] = createMember(n, age, gd); } public float avgAge(){ float avg = 0; int memberNo = 0; if (father != null){ memberNo++;avg += father.getAge(); } if(mother != null){ memberNo++;avg += mother.getAge(); } for (int i = 0; i < nextChild; i++){ memberNo++; avg += children[i].getAge(); } return (memberNo > 0) ? avg/memberNo : 0 ; } };
Παράδειγμα public class FamilyTest{ public static void main(String arg[]){ intmaxChildren = Integer.parseInt(args[0]); Family family = new Family(args[1], maxChildren); if(args[2].equals(“noFather”) == false) family.setFather(args[2], Integer.parseInt(args[3]), Integer.parseInt(args[4])); if(args[5].equals(“noMother”) == false) family.setMother(args[5], Integer.parseInt(args[6]), Integer.parseInt(args[7])); for(inti=0; i < maxChildren; i++) family.addChild(args[8+i], Integer.parseInt(args[9+i]), Integer.parseInt(args[10+i])); System.out.println("Average Family Age : " + family.avgAge()); Member orphan = new Member(“Jim”, 20, 1) }
Παράδειγμα Γιατί έχω σχέση σύνθεσης ?
Quiz class A{ private int x; private float y; public A(int ax, float ay) { x=ax; y=ay; } public void ma(B b){ b.mb(); } } class B{ private int z; private int w; public B(int az, int aw) { z=az; w=aw; } public void mb(){ z--; w++; } } Πώς σχετίζονται ??
Quiz class A{ private int x; private float y; public A(int ax, float ay) { x=ax; y=ay; } public void ma(){ B b = new B(10, 20) b.mb(); } } class B{ private int z; private int w; public B(intaz, int aw) { z=az; w=aw; } public void mb(){ z--; w++; } } Πώς σχετίζονται ??
Quiz class A{ private int x; private B b; public A(int ax, B ab) { x=ax; b=ab; } public void ma(){ b.mb(); } } class B{ private int z; private int w; public B(int az, int aw) { z=az; w=aw; } public void mb(){ z--; w++; } } Πώς σχετίζονται ??