ΟΙΚΟΝΟΜΙΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. ΜΕΤΑΠΤΥΧΙΑΚΟ ΔΙΠΛΩΜΑ ΕΙΔΙΚΕΥΣΗΣ (MSc) στα ΠΛΗΡΟΦΟΡΙΑΚΑ ΣΥΣΤΗΜΑΤΑ ΔΙΠΛΩΜΑΤΙKH ΕΡΓΑΣΙΑ

Σχετικά έγγραφα
ΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ Αξιολόγηση των Σχεδιαστικών Προτύπων και της Ποιότητας του Λογισμικού μέσω Μετρικών, στις Περιπτώσεις Προσθήκης Λειτουργικότητας και

Εισαγωγή στη Σχεδίαση Λογισμικού

Πίνακας Περιεχομένων. μέρος A 1 Εισαγωγή στην Τεχνολογία Λογισμικού

Διαγράμματα Κλάσεων στη Σχεδίαση

Μοτίβα Σχεδίασης (Design Patterns)

ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΗΣ ΑΝΑΛΥΣΗ Πρότυπα Σχεδίασης. Ιωάννης Σταμέλος Βάιος Κολοφωτιάς Πληροφορική

Αρχιτεκτονική Λογισμικού

ΟΙΚΟΝΟΜΙΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ. ΜΕΤΑΠΤΥΧΙΑΚΟ ΔΙΠΛΩΜΑ ΕΙΔΙΚΕΥΣΗΣ (MSc) στα ΠΛΗΡΟΦΟΡΙΑΚΑ ΣΥΣΤΗΜΑΤΑ ΔΙΠΛΩΜΑΤΙKH ΕΡΓΑΣΙΑ

ΑΥΤΟΜΑΤΗ ΑΝΑΚΑΤΑΣΚΕΥΗ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΩΝ ΔΙΕΠΑΦΩΝ Η ΜΕΤΑΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ ΕΞΕΙΔΙΚΕΥΣΗΣ. Υποβάλλεται στην

Αντικειμενοστρεφής Προγραμματισμός

Ελληνικό Ανοικτό Πανεπιστήµιο. Βασικές έννοιες αντικειµενοστρεφούς τεχνολογίας. ρ. Πάνος Φιτσιλής

Στόχοι της Πτυχιακής

Ανάπτυξη & Σχεδίαση Λογισμικού (ΗΥ420)

Οδηγίες Συγγραφής και Αξιολόγησης Εργασιών του μαθήματος

ΑΡΦΕ ΑΝΣΙΚΕΙΜΕΝΟΣΡΕΥΟΤ ΠΡΟΓΡΑΜΜΑΣΙΜΟΤ. Ιωάννης Φατζηλυγερούδης Αναπληρωτής Καθηγητής Τμήμα Μηχ/κών Η/Υ και Πληροφορικής Πανεπιστήμιο Πατρών

Αυτόματη Ανακατασκευή Π ρογραμματισμώ ν Διεπαφών

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ Π ΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ Π ΕΡΙΒΑΛΛΟΝ

Ειδικά θέματα τεχνολογίας λογισμικού

ΠΛΗΡΟΦΟΡΙΚΗ Γ ΤΑΞΗΣ ΓΕΛ ΚΛΕΙΩ ΣΓΟΥΡΟΠΟΥΛΟΥ. ΣΥΓΧΡΟΝΑ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΑ ΠΕΡΙΒΑΛΛΟΝΤΑ Αντικειμενοστραφής Προγραμματισμός

ΠΡΟΓΡΑΜΜΑ ΣΠΟΥΔΩΝ ΠΛΗΡΟΦΟΡΙΚΗ, Γ ΤΑΞΗ ΓΕΝΙΚΟΥ ΛΥΚΕΙΟΥ

ΠΛΗΡΟΦΟΡΙΚΗ Ι JAVA Τμήμα θεωρίας με Α.Μ. σε 8 & 9 18/10/07

Μοντελοποίηση Πεδίου

ΕΝΙΑΙΟ ΠΛΑΙΣΙΟ ΠΡΟΓΡΑΜΜΑΤΟΣ ΣΠΟΥΔΩΝ

06 Αντικειμενοστρεφής ανάλυση και σχεδιασμός

Περιεχόµενα. Πληροφοριακά Συστήµατα: Κατηγορίες και Κύκλος Ζωής. Π.Σ. ιαχείρισης Πράξεων. Π.Σ. ιοίκησης. Κατηγορίες Π.Σ. Ο κύκλος ζωής Π.Σ.

Εισαγωγή στην Πληροφορική

ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΙΓΑΙΟΥ

Διαδικασίες παραγωγής λογισμικού. Βασικές αρχές Τεχνολογίας Λογισμικού, 8η αγγ. έκδοση

ΥΠΟΛΟΓΙΣΤΙΚΕΣ ΤΕΧΝΙΚΕΣ ΓΙΑ ΣΥΣΤΗΜΑΤΑ ΜΕΤΑΔΟΣΗΣ ΠΛΗΡΟΦΟΡΙΑΣ

Κεφάλαιο 10 ο Υποπρογράµµατα

4. Συντακτικό μιας γλώσσας είναι το σύνολο των κανόνων που ορίζει τις μορφές με τις οποίες μια λέξη είναι αποδεκτή.

Σχεδιασµός βασισµένος σε συνιστώσες

Σχεδίαση Κλάσεων. Γρηγόρης Τσουµάκας. Τµήµα Πληροφορικής, Αριστοτέλειο Πανεπιστήµιο Θεσσαλονίκης. Έκδοση:

Οντοκεντρικός Προγραμματισμός

Προγραμματισμός Η/Υ. Προτεινόμενα θέματα εξετάσεων Εργαστήριο. Μέρος 1 ό. ΤΕΙ Λάρισας- Σχολή Τεχνολογικών Εφαρμογών Τμήμα Πολιτικών Έργων Υποδομής

Πληροφορική 2. Τεχνολογία Λογισμικού

Υποδείγματα Ανάπτυξης

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ

Κεφάλαιο 2.3: Προγραμματισμός. Επιστήμη ΗΥ Κεφ. 2.3 Καραμαούνας Πολύκαρπος

ΣΧΕ ΙΑΣΗ ΑΝΤΙΚΕΙΜΕΝΩΝ ΜΕ ΑΡΜΟ ΙΟΤΗΤΕΣ. Ορισµός σχεδιαστικών προτύπων Εφαρµογή των 9 GRASP προτύπων

ΕΡΓΟ: Συγκριτική Μελέτη Λογισμικού Βιβλιοθηκών, Λογισμικού Εφαρμογών Ανοικτού Κώδικα και Βιομηχανικού Λογισμικού MIS:

ΚΕΦΑΛΑΙΟ 5. Κύκλος Ζωής Εφαρμογών ΕΝΟΤΗΤΑ 2. Εφαρμογές Πληροφορικής. Διδακτικές ενότητες 5.1 Πρόβλημα και υπολογιστής 5.2 Ανάπτυξη εφαρμογών

Εισαγωγή σε αντικειμενοστραφή concepts. Και λίγη C#

Πληροφορική ΙΙ Εισαγωγή στις Βάσεις Δεδομένων. Τμήμα Λογιστικής

Πληροφοριακά Συστήματα Διοίκησης Ενότητα 1: Βασικές Αρχές Αντικειμενοστραφούς Σχεδίασης Συστημάτων και Εφαρμογών (1ο Μέρος)

Έλεγχος Συνένωσης και Διασφάλιση Ποιότητας

Ιστορικό. *Ομάδα ανάπτυξης: Γρεασίδης Θοδωρής: 265 Κουτσαυτίκης Δημήτρης: 258 Μπούρα Βάγια: 257 Πετράκη Ελένη: 266 Φουντά Σταυρούλα: 256

Κεφάλαιο 7 : Είδη, Τεχνικές, και Περιβάλλοντα Προγραµµατισµού

ΕΠΛ233 Βιβλιοθήκες και Προσδιοριστές Πρόσβασης στην JAVA

ιδάσκων: ηµήτρης Ζεϊναλιπούρ

Σημειώσεις στο μάθημα «Στοιχεία Προγραμματισμού σε Γραφικό Περιβάλλον»

ΗΥ562 Προχωρημένα Θέματα Βάσεων Δεδομένων Efficient Query Evaluation over Temporally Correlated Probabilistic Streams

ΕΙΔΗ,ΤΕΧΝΙΚΕΣ ΚΑΙ ΠΕΡΙΒΑΛΛΟΝΤΑ ΠΡΟΓΡΑΜΜΑΤΙ- ΣΜΟΥ

Γεώργιος Φίλιππας 23/8/2015

Κεφάλαιο 2ο. Κατανοώντας την αντικειμενοστρέφεια

ΑΕΠΠ Ερωτήσεις θεωρίας

Απαιτήσεις Λογισμικού

Ανάπτυξη & Σχεδίαση Λογισμικού (ΗΥ420)

Κεφάλαιο 6 ο Εισαγωγή στον Προγραμματισμό 1

5 ΕΙΣΑΓΩΓΗ ΣΤΗ ΘΕΩΡΙΑ ΑΛΓΟΡΙΘΜΩΝ

2.1 Αντικειµενοστρεφής προγραµµατισµός

Διαδικασίες παραγωγής λογισμικού. I. Sommerville 2006 Βασικές αρχές Τεχνολογίας Λογισμικού, 8η αγγ. έκδοση Κεφ. 4

Computing. Νοέμβριος Έκδοση 1.0

Πληροφοριακά Συστήματα Διοίκησης. Επισκόπηση μοντέλων λήψης αποφάσεων Τεχνικές Μαθηματικού Προγραμματισμού

Δομημένος Προγραμματισμός

Δείχτες Επιτυχίας και Δείχτες Επάρκειας

Κεφ. 2 Θέματα Θεωρητικής Επιστήμης Υπολογιστών. Κοντογιάννης Βασίλειος ΠΕ19

Α. Ερωτήσεις Ανάπτυξης

Η ΜΕΤΑΠΤΥΧΙΑΚΗ ΕΡΓΑΣΙΑ ΕΞΕΙΔΙΚΕΥΣΗΣ. Υ7ΐοβάλλεται στην

. Μεθοδολογία Προγραμματισμού. Μοτίβα σχεδίασης (Design Patterns) Νικόλαος Πεταλίδης. Εισαγωγή Εαρινό Εξάμηνο 2014

Προγραμματισμός ΙI (Θ)

Τεχνολογία Λογισμικού. Ενότητα 1: Εισαγωγή στην UML Καθηγητής Εφαρμογών Ηλίας Γουνόπουλος Τμήμα Διοίκησης Επιχειρήσεων (Γρεβενά)

ΤΕΙ ΚΕΝΤΡΙΚΗΣ ΜΑΚΕΔΟΝΙΑΣ

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ ΜΑΡΙΑ Σ. ΖΙΩΓΑ ΚΑΘΗΓΗΤΡΙΑ ΠΛΗΡΟΦΟΡΙΚΗΣ ΕΙΣΑΓΩΓΗ ΣΤΟΝ ΠΡΟΓΡΑΜΜΑΤΙΣΜΟ

Τεχνολογίες Υλοποίησης Αλγορίθµων

ΑΞΙΟΠΙΣΤΙΑ ΥΛΙΚΟΥ ΚΑΙ ΛΟΓΙΣΜΙΚΟΥ

ΑΝΑΛΥΣΗ ΑΠΑΙΤΗΣΕΩΝ ανάλυση απαιτήσεων Σε αυτό το μάθημα θα ασχοληθούμε με : Δημιουργία μοντέλων

XP μέθοδος για τη Διαχείριση Έργων Λογισμικού

ΑΝΑΠΤΥΞΗ ΕΦΑΡΜΟΓΩΝ ΣΕ ΠΡΟΓΡΑΜΜΑΤΙΣΤΙΚΟ ΠΕΡΙΒΑΛΛΟΝ ΕΠΙΜΕΛΕΙΑ: ΜΑΡΙΑ Σ. ΖΙΩΓΑ ΚΑΘΗΓΗΤΡΙΑ ΠΛΗΡΟΦΟΡΙΚΗΣ 1 ΟΥ ΚΕΦΑΛΑΙΟΥ ΑΝΑΛΥΣΗ ΠΡΟΒΛΗΜΑΤΟΣ

Γουλή Ευαγγελία. 1. Εισαγωγή. 2. Παρουσίαση και Σχολιασµός των Εργασιών της Συνεδρίας

Αρχές Προγραμματισμού Υπολογιστών

Υπολογιστικής Σκέψης

Αρχές Τεχνολογίας Λογισμικού Εργαστήριο

Τεχνολογία Λογισμικού

Τεχνολογία Λογισμικού

Περιεχόμενα. Ανάλυση προβλήματος. Δομή ακολουθίας. Δομή επιλογής. Δομή επανάληψης. Απαντήσεις. 1. Η έννοια πρόβλημα Επίλυση προβλημάτων...

Κεφάλαιο 4 Σχεδίαση Βάσεων Δεδομένων

Εισαγωγή στον Αντικειμενοστρεφή Προγραμματισμό Διάλεξη #2

ΚΕΦΑΛΑΙΟ 10 ΥΠΟΠΡΟΓΡΑΜΜΑΤΑ

METROPOLIS. Ένα περιβάλλον σχεδιασμού για ετερογενή συστήματα

Αντικειμενοστρέφεια. Henri Matisse, Harmony in Red, Κωστής Σαγώνας Νίκος Παπασπύρου

ΠΟΛΥΜΟΡΦΙΣΜΟΣ. 4.1 Κληρονομικότητα και Αρχή της Υποκατάστασης

1 Συστήματα Αυτοματισμού Βιβλιοθηκών

Τεχνολογία Λογισμικού & Ανάλυση Συστημάτων

ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΗΣ ΑΝΑΛΥΣΗ Επιχειρηματική Μοντελοποίηση. Ιωάννης Σταμέλος Βάιος Κολοφωτιάς Πληροφορική

Περιεχόμενο του μαθήματος

Περιεχόμενο του μαθήματος

Κλάσεις και Αντικείµενα

ΔΟΜΙΚΗ ΜΟΝΤΕΛΟΠΟΙΗΣΗ ΚΑΙ ΜΟΝΤΕΛΟΠΟΙΗΣΗ ΣΥΜΠΕΡΙΦΟΡΑΣ (9)

ΕΝΤΟΠΙΣΜΟΣ ΠΡΟΒΛΗΜΑΤΩΝ ΕΣΦΑΛΜΕΝΗΣ ΧΡΗΣΗΣ ΚΛΗΡΟΝΟΜΙΚΟΤΗΤΑΣ ΣΕ ΑΝΤΙΚΕΙΜΕΝΟΣΤΡΕΦΗ ΣΥΣΤΗΜΑΤΑ ΛΟΓΙΣΜΙΚΟΥ

Transcript:

ΟΙΚΟΝΟΜΙΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ ΜΕΤΑΠΤΥΧΙΑΚΟ ΔΙΠΛΩΜΑ ΕΙΔΙΚΕΥΣΗΣ (MSc) στα ΠΛΗΡΟΦΟΡΙΑΚΑ ΣΥΣΤΗΜΑΤΑ ΔΙΠΛΩΜΑΤΙKH ΕΡΓΑΣΙΑ «Αναδόμηση και πρότυπα σχεδίασης λογισμικού» Λάμπρος Τσολάκος Μ312005 ΑΘΗΝΑ, ΑΠΡΙΛΙΟΣ 2014

ΜΕΤΑΠΤΥΧΙΑΚΟ ΔΙΠΛΩΜΑ ΕΙΔΙΚΕΥΣΗΣ (MSc) στα ΠΛΗΡΟΦΟΡΙΑΚΑ ΣΥΣΤΗΜΑΤΑ ΔΙΠΛΩΜΑΤΙKH ΕΡΓΑΣΙΑ «Αναδόμηση και πρότυπα σχεδίασης λογισμικού» Λάμπρος Τσολάκος Μ312005 Επιβλέπων Καθηγητής: Εμμανουήλ Γιακουμάκης Εξωτερικός Κριτής: Ονοματεπώνυμο ΟΙΚΟΝΟΜΙΚΟ ΠΑΝΕΠΙΣΤΗΜΙΟ ΑΘΗΝΩΝ ΤΜΗΜΑ ΠΛΗΡΟΦΟΡΙΚΗΣ ΑΘΗΝΑ, ΑΠΡΙΛΙΟΣ 2014

Περίληψη Η Διπλή Αποστολή είναι ένα σημαντικό χαρακτηριστικό που δεν υποστηρίζεται άμεσα στις αντικειμενοστρεφείς γλώσσες προγραμματισμού. Σε αυτές, ο ενδεδειγμένος τρόπος προσομοίωσης της Διπλής Αποστολής, είναι το πρότυπο Επισκέπτης. Το πρότυπο Επισκέπτης είναι η κατάλληλη μέθοδος για διαχωρισμό της κατάστασης μιας ιεραρχίας αντικειμένων από την συμπεριφορά τους, την προσθήκη πολλών νέων λειτουργιών χωρίς μόλυνση των κλάσεών τους με μη-σχετιζόμενες λειτουργίες και την ομαδοποίηση των σχετιζόμενων λειτουργιών σε κοινή κλάση. Τα προηγούμενα δεν είναι εφικτά με πολυμορφισμό. Επίσης, με την Διπλή Αποστολή επιτελούνται λειτουργίες βάσει του τύπου δύο αντικειμένων. Η Διπλή Αποστολή στην φυσική της μορφή, προσεγγίζει αρκετά τη λύση του Expression Problem, επιτρέποντας προσθήκη νέων τύπων και λειτουργιών χωρίς τροποποίηση των ήδη υφισταμένων. Η παρούσα μέθοδος προτείνει την εξαγωγή συστάσεων αναδόμησης εισάγοντας το πρότυπο Επισκέπτης. Διασφαλίζει την διατήρηση συμπεριφοράς του κώδικα και την υλοποιησιμότητα των προτεινόμενων αναδομήσεων, βάσει ενός συνόλου προϋποθέσεων. 4

Περιεχόμενα Περίληψη... 4 1. Εισαγωγή... 7 1.1 Σκοπός και συμβολή της εργασίας... 8 1.2 Δομή... 10 2. Αναδόμηση κώδικα και Πρότυπα Σχεδίασης... 12 2.1 Αναδόμηση κώδικα... 12 2.1.1 Ορισμός... 12 2.1.2 Χρησιμότητα της αναδόμησης... 12 2.1.3 Χρονική καταλληλότητα για εφαρμογή αναδόμησης... 13 2.1.4 Είδη αναδόμησης... 14 2.2 Πρότυπα Σχεδίασης... 16 2.2.1 Ορισμός και τρόπος περιγραφής Προτύπων Σχεδίασης... 16 2.2.2 Κατηγοριοποίηση Προτύπων Σχεδίασης... 17 2.2.3 Σχεδίαση για Αλλαγή... 20 2.3 Αναδόμηση με Πρότυπα... 22 2.4 Αναδόμηση με απαλοιφή Κακών Οσμών... 25 3. Πρότυπο Επισκέπτης... 33 3.1 Παρουσίαση Προτύπου Επισκέπτης... 33 3.2 Επισκόπηση βιβλιογραφίας... 39 3.2.1 Παραλλαγές προτύπου Επισκέπτης... 39 3.2.2 Αναδόμηση στο πρότυπο Επισκέπτης... 41 4. Αντι-πρότυπο RunTime Type Identification (RTTI)... 42 4.1 Πρόβλημα Έκφρασης... 42 4.2 Διπλή Αποστολή μια προσπάθεια επίλυσης του Προβλήματος Έκφρασης... 44 4.2.1 Η έννοια της Διπλής Αποστολής... 44 4.2.2 Μηχανισμοί υλοποίησης της Διπλής Αποστολής... 46 4.2.3 Προβλήματα που επιλύει το πρότυπο Διπλή Αποστολή... 48 5. Απαλοιφή RTTI με το πρότυπο Επισκέπτης... 51 5.1 Επισκόπιση βιβλιογραφίας... 51 5.1.1 Ανίχνευση προβλημάτων σχεδίασης... 51 5.1.2 Ανίχνευση αντι-προτύπου RTTI... 53 5.2 Προτεινόμενη Μέθοδος... 55 5.2.1 Ανίχνευση αντι-προτύπου RTTI... 55 5.2.2 Προϋποθέσεις... 58 5.2.3 Επιλογή αναδόμησης στο πρότυπο Επισκέπτης ή σε πολυμορφισμό... 60 5.2.4 Αλγόριθμος... 67 5.2.5 Κριτήρια Απόφασης... 75 6. Αποτελέσματα... 77 6.1 Χαρακτηριστικά έργων και απόδοση παραχθέντος εργαλείου σε αυτά... 77 6.2 Σύγκριση αποτελεσμάτων plugins RTTI - TypeChecking... 78 6.3 Περιπτώσεις αναδόμησης ως συνάρτηση του ποσοστού κάλυψης των υποκλάσεων... 79 7. Συμπεράσματα... 85 ΠΑΡΑΡΤΗΜΑ... 87 Παράρτημα Α. Παράδειγμα εφαρμογής του προτύπου Επισκέπτης... 87 Παράρτημα Β. Παράδειγμα υλοποίησης Διπλής Αποστολής ως σειρά από Απλές Αποστολές... 89 Παράρτημα Γ. Αλγόριθμος ανίχνευσης τμημάτων σε μορφή ψευδοκώδικα... 93 Γ1. Ανίχνευση RTTI τμημάτων σε επίπεδο μεθόδου... 93 5

Γ2. Ανίχνευση RTTI τμημάτων σε επίπεδο κλάσης... 93 Βιβλιογραφία... 97 6

1. Εισαγωγή Ο τομέας της τεχνολογίας λογισμικού παρουσιάζει τα τελευταία χρόνια αυξανόμενα επίπεδα ωρίμανσης. Σύμφωνα με το Software Engineering Body Of Knowledge (SWEBOK) [1], η τεχνολογία λογισμικού μόλις τα τελευταία χρόνια έχει αρχίσει να προσδιορίζει σαφέστερα τα όρια και το περιεχόμενό της, και ο κλάδος να τυγχάνει ευρύτερης αναγνωρισιμότητας. Η εμφάνιση των πρώτων γλωσσών προγραμματισμού κατά την δεκαετία του 1950, συνετέλεσε στην εδραίωση της έννοιας της αφαίρεσης (abstraction), ως ένα μέσο αντιμετώπισης της υπολογιστικής πολυπλοκότητας. Καθοριστικό ρόλο προς την αντιμετώπιση της υπολογιστικής πολυπλοκότητας διαδραμάτισαν οι εργασίες των Dijkstra [2] (1968) "Go To Statement Considered Harmful", και Parnas [3] (1972), ο οποίος εισήγαγε τις θεμελιώδεις έννοιες της τμηματικότητας (modularity) και της απόκρυψης πληροφορίας (information hiding). Ο όρος «τεχνολογία λογισμικού» (software engineering) εμφανίστηκε για πρώτη φορά το 1968, ως ο τίτλος για το πρώτο διεθνές συνέδριο τεχνολογίας λογισμικού υπό τη χορηγία του NATO. Προϊόν του συνεδρίου είναι μια έκθεση που καθορίζει τη συνιστώμενη μεθοδολογία ανάπτυξης του λογισμικού [4]. Το επιστημονικό πεδίο της τεχνολογίας λογισμικού επινοήθηκε ώστε να αντιμετωπιστεί η φτωχή ποιότητα του λογισμικού, τα έργα λογισμικού να τεθούν εντός ορίων χρόνου και κόστους, και να διασφαλισθεί ότι το λογισμικό κατασκευάζεται συστηματικά, αυστηρά, ώστε να είναι μετρήσιμο και εντός χρόνου, προϋπολογισμού και προδιαγραφών. Ο τομέας της μηχανικής (engineering), ήδη είχε αντιμετωπίσει τα προηγούμενα ζητήματα, επομένως οι ίδιες αρχές μπορούν να εφαρομοστούν και στο λογισμικό. Η έλλειψη καλών πρακτικών ανάπτυξης λογισμικού εκείνη την εποχή έγινε αντιληπτή ως «κρίση λογισμικού» [4] [5]. Ο Boehm [6] κατέγραψε οριμένες κεντρικές εξελίξεις του τομέα στο βιβλίο του Software Engineering Economics (1981). Σε αυτές συγκαταλέγεται το Constructive Cost Model (COCOMO), το οποίο οποίο συσχετίζει την προσπάθεια ανάπτυξης λογισμικού για ένα πρόγραμμα, εκφρασμένη σε ανθρωπο-έτη T, με τις γραμμές πηγαίου κώδικα (source lines of code - SLOC), μέσω της σχέσης T = k * (SLOC) (1+x). 7

Το βιβλίο αναλύει 63 έργα λογισμικού και συμπεραίνει πως το κόστος διόρθωσης σφαλμάτων κλιμακώνεται καθώς γίνεται η μετάβαση του έργου προς την χρήση του. Επίσης, υποστηρίζει ότι ο πιο καθοριστικός παράγοντας για το κόστος του λογισμικού είναι η ικανότητα της ομάδας ανάπτυξης. Διακρίνει τις εξής φάσεις στον κύκλο ζωής του λογισμικού κατά σειρά εμφάνισης: Εφικτότητα (Feasibility), Προδιαγραφή Απαιτήσεων (Plans and requirements), Σχεδίαση (Product design), Προγραμματισμός (Programming), Ενοποίηση και Έλεγχος (Integration and Test), Συντήρηση (Maintenance), Σταδιακή κατάργηση (Phaseout). Στις αρχικές φάσεις υφίσταται μεγαλύτερη αβεβαιότητα στον προσδιορισμό του κόστους, ενώ το κόστος διόρθωσης σφαλμάτων είναι μεγαλύτερο για σφάλματα στις πρώτες φάσεις, και ακόμα μεγαλύτερο σε όσο μεταγενέστερη φάση γίνει αντιληπτό. Τα πρότυπα σχεδίασης (design patterns) αποτελούν αφηρημένα επαναχρησιμοποιήσιμα σχέδια, που μπορούν να εξατομικευτούν ανάλογα με το ειδικότερο πραγματικό πρόβλημα. Επειδή η φάση της σχεδίασης είναι σημαντική λόγω του μεγαλύτερου κόστους διορθώσεων από επόμενες φάσεις, τα πρότυπα σχεδίασης μπορούν να παράσχουν ευελιξία σε κάποιες παραμέτρους του συστήματος. Όμως, το πρόβλημα στις αρχικές φάσης ζωής του λογισμικού είναι λιγότερο σαφές, επομένως η προσπάθεια εύρεσης της ακριβούς λύσης μπορεί να εισαγάγει λειτουργικότητα που δε θα χρησιμοποιηθεί και πολυπλοκότητα. Αυτή την πολυπλοκότητα επιχειρεί να μειώσει η μέθοδος της αναδόμησης (refactoring), η οποία αναδιαρθρώνει τη δομή του κώδικα χωρίς να αλλάξει την παρατηρούμενη συμπεριφορά του. Στόχος της είναι να διατηρήσει την σχεδίαση ευκολότερα ορατή σε επίπεδο κώδικα, καθιστώντας το λογισμικό πιο κατανοητό, συντηρήσιμο, επεκτάσιμο. Αρκεί ένα αρχικό σχέδιο που να δίνει μια λογική λύση απλή, η οποία να μπορεί εύκολα να αναδομηθεί σε εναλλακτικά σχέδια. Καθώς στην πορεία καθίσταται πιο ορατή η βέλτιστη λύση, η εισαγωγή εναλλακτικών σχεδίων μπορεί να γίνει σχετικά εύκολα. Ένας τρόπος εισαγωγής εναλλακτικού σχεδίου σε μεταγενέστερη φάση από τη σχεδίαση, είναι η αναδόμηση με χρήση προτύπων σχεδίασης. 1.1 Σκοπός και συμβολή της εργασίας Η παρούσα εργασία έχει ως σκοπό να συνεισφέρει στην ανίχνευση ανεπιθύμητων προτύπων στον κώδικα, τα οποία μπορούν να μειωθούν/απαλειφθούν με αναδόμηση με πρότυπα σχεδίασης. Ειδικότερα, σε αυτή την διπλωματική εργασία μελετάται το ζήτημα της αυτοματοποιημένης αναδόμησης προς το πρότυπο επισκέπτης. 8

Η αυτοματοποίηση της αναδόμησης μειώνει την δυσκολία, τον χρόνο εφαρμογής της, καθώς και την πιθανότητα εισαγωγής σφαλμάτων εξαιτίας λανθασμένης εφαρμογής της. Επίσης, ενίοτε παρέχει την δυνατότητα άμεσου ελέγχου του αποτελέσματός της είτε με εφαρμογή της σε αντίγραφο του κώδικα, είτε με κριτήρια αξιολόγησής της πριν την εφαρμογή της. Στη βιβλιογραφία παρατηρείται έλλειψη αυτοματοποιημένων εργαλείων για ανίχνευση προβλημάτων σχεδίασης στον κώδικα ή/και αναδόμηση που αξιοποιεί συγκεκριμένα πρότυπα σχεδίασης. Τα υφιστάμενα εργαλεία υποστηρίζουν κυρίως στοιχειώδη και όχι σύνθετα είδη αναδόμησης. Επίσης, είναι δύσκολος ο εντοπισμός σημείων του κώδικα όπου είναι αξιοποιήσιμο ένα συγκεκριμένο πρότυπο σχεδίασης. Διότι εκτός από την εύρεση συγκεκριμένων αντι-προτύπων στον κώδικα, απαιτείται ο έλεγχος της εννοιολογικής καταλληλότητας για χρήση του προτύπου, που επιτυγχάνεται με εμπειρικά ποιοτικά κριτήρια. Η παρούσα εργασία χρησιμοποιεί ως αφετηρία την εργασία των Τσάνταλη και Χατζηγεωργίου [7], στην οποία ανιχνεύονται ευκαιρίες αναδόμησης με πολυμορφισμό. Ειδικότερα, ανιχνεύουν δύο περιπτώσεις λανθασμένης αντικατάστασης του πολυμορφισμού από υποθετικές δηλώσεις (switch/if statements). Η πρώτη περίπτωση εμφανίζεται ως σύγκριση της τιμής μιας μεταβλητής που αναπαριστά την τρέχουσα κατάσταση ενός αντικειμένου με ένα σύνολο ονομασμένων σταθερών (στατικών σταθερών που ανήκουν σε όλα τα στιγμιότυπα του αντικειμένου). Η δεύτερη εμφανίζεται ως ανάκτηση του τύπου της υποκλάσης μιας αναφοράς σε αντικείμενο σε χρόνο εκτέλεσης (RunTime Type Identification - RTTI). Η μέθοδος που προτείνει το παρόν κείμενο, χρησιμοποιεί την δεύτερη περίπτωση (RTTI), διότι το πρότυπο επισκέπτης προϋποθέτει την ύπαρξη της ιεραρχίας υποκλάσεων. Η αναδόμηση με πολυμορφισμό δεν είναι πάντα κατάλληλη. Αντί αυτού συνιστάται η αναδόμηση προς το πρότυπο επισκέπτης, αν ο κώδικας στην υποθετική δήλωση ταιριάζει καλύτερα στην κλάση που ήδη βρίσκεται και όχι στις υποκλάσεις του τύπου της αναφοράς. Σε αυτή την περίπτωση, η απαλοιφή της υποθετικής δήλωσης γίνεται με εξαγωγή του κώδικα κάθε κλάδου της υποθετικής δήλωσης σε ξεχωριστή μέθοδο. Στη συνέχεια, κάθε τέτοια μέθοδος καλείται από την αντίστοιχη υποκλάση του τύπου της αναφοράς, με χρήση της τεχνικής του delegation. Η συνεισφορά της προτεινόμενης μεθόδου, είναι αφενός ο εντοπισμός επιπλέον περιπτώσεων του αντι-προτύπου RTTI. Ο εντοπισμός του σε υποθετικές δομές if-elseif, επεκτείνεται και σε δομές if-if διαδοχικών και αμοιβαίως αποκλειόμενων. 9

Αφετέρου, σημαντική συνεισφορά αποτελεί η ανίχνευση περιπτώσεων που χρειάζονται εφαρμογή του προτύπου επισκέπτης αντί του πολυμορφισμού, αποφεύγοντας τη «μόλυνση» της ιεραρχίας υποκλάσεων του τύπου της αναφοράς με συμπεριφορά που ανήκει εννοιολογικά στην κλάση που περιέχει την υποθετική δήλωση. Επίσης, η παρούσα εργασία συμβάλλει στον καλύτερο έλεγχο της εννοιολογικής ορθότητας της αναδόμησης είτε στο πρότυπο επισκέπτη είτε με πολυμορφισμό, μέσω εμπειρικών κριτηρίων για το πλήθος των υποκλάσεων της ιεραρχίας που καλύπτονται από τους κλάδους της υποθετικής δήλωσης. Προτείνεται με μεγαλύτερη βεβαιότητα μια αναδόμηση που καλύπτει όλες τις υφιστάμενες υποκλάσεις της ιεραρχίας. 1.2 Δομή Η εργασία αποτελείται από τα εξής κεφάλαια: Στο Κεφάλαιο 2 μελετώνται οι έννοιες της αναδόμησης κώδικα, των προτύπων σχεδίασης. Επίσης, μελετάται η αναδόμηση με πρότυπα και η αναδόμηση με απαλοιφή κακών οσμών. Το Κεφάλαιο 3 παρουσιάζει το πρότυπο σχεδίασης επισκέπτης, καθώς και σχετική βιβλιογραφία. Η βιβλιογραφία αφορά σε παραλλαγές του προτύπου για περιορισμό των αρνητικών συνεπειών του, καθώς και βιβλιογραφία για αναδόμηση στο πρότυπο επισκέπτης. Το Κεφάλαιο 4 πραγματεύεται τη βασική έννοια του αντι-προτύπου RunTime Type Identification (RTTI). Εκθέτει το πρόβλημα έκφρασης, το οποίο αφορά την προσθήκη νέων τύπων δεδομένων και νέων λειτουργιών. Οι δύο αυτές μορφές επέκτασης απαιτείται να μπορούν να εκφραστούν χωρίς τροποποίηση των υφιστάμενων τύπων ή των υφιστάμενων πελατών τους, διατηρώντας την ασφάλεια τύπων. Στη συνέχεια, παρουσιάζει την τεχνική της διπλής αποστολής. Η διπλή αποστολή είναι ένας τρόπος επιλογής της υλοποίησης μιας λειτουργίας, βάσει του τύπου δύο ορισμάτων. Η διπλή αποστολή αποτελεί μια καλή προσέγγιση της λύσης στο πρόβλημα έκφρασης. Μελετάται το RunTime Type Identification (RTTI), το οποίο ως λανθασμένος μηχανισμός υλοποίησης της διπλής αποστολής εισάγει διπλότυπα και πολυπλοκότητα. Μελετάται η υλοποίηση της διπλής αποστολής ως ακολουθία δύο απλών αποστολών. Επίσης, παρουσιάζονται τα προβλήματα που επιλύει η διπλή αποστολή. Το Κεφάλαιο 5 παρουσιάζει την προτεινόμενη μέθοδο, για απαλοιφή του αντιπροτύπου RTTI με αναδόμηση στο πρότυπο επισκέπτης. Παραθέτει σχετική βιβλιογραφία, και στη συνέχεια αναλύει την προτεινόμενη μέθοδο. 10

Ο εντοπισμός περιπτώσεων αναδόμησης αποτελείται από τις υποενότητες 5.2.1 Ανίχνευση αντι-προτύπου RTTI, 5.2.2 Προϋποθέσεις, 5.2.3 Επιλογή αναδόμησης στο πρότυπο Επισκέπτης ή σε πολυμορφισμό. Ειδικότερα, η ενότητα 5.2.1 ασχολείται με τον ορισμό του RTTI τμήματος κώδικα. Η ενότητα 5.2.2 αφορά τις προϋποθέσεις αναδόμησης προς το πρότυπο Επισκέπτης. Οι υποενότητές της 5.2.2 αφορούν την αναδόμηση χωρίς διεπαφή επισκέπτη (5.2.2.1 Προϋποθέσεις αναδόμησης σε Διπλή Αποστολή) ή με διεπαφή επισκέπτη (5.2.2.2 Προϋποθέσεις αναδόμησης στο σχεδιαστικό πρότυπο Επισκέπτης). Η ενότητα 5.2.3 αφορά στην επιλογή αν η αναδόμηση θα γίνει προς το πρότυπο Επισκέπτης (5.2.2) ή με πολυμορφισμό. Η ενότητα 5.2.4 (Αλγόριθμος), περιγράφει σε χαμηλότερο επίπεδο, πώς υλοποιήθηκαν τα κριτήρια των προηγούμενων ενοτήτων. Η ενότητα 5.2.5 παρουσιάζει ποιοτικά κριτήρια για τελική αποδοχή ή απόρριψη μιας προτεινόμενης αναδόμησης. Το κεφάλαιο 6 παρουσιάζει αποτελέσματα του παραχθέντος εργαλείου σε διάφορα έργα λογισμικού. Το κεφάλαιο 7 παραθέτει τα συμπεράσματα της εργασίας. 11

2. Αναδόμηση κώδικα και Πρότυπα Σχεδίασης 2.1 Αναδόμηση κώδικα 2.1.1 Ορισμός Σύμφωνα με τον Fowler [8], υφίστανται δύο ορισμοί για την αναδόμηση, ένας σε μορφή ουσιαστικού και ένας σε μορφή ρήματος. Αναδόμηση (ουσιαστικό): μια μεταβολή στην εσωτερική δομή ενός λογισμικού, η οποία το καθιστά ευκολότερα κατανοητό και οικονομικότερα τροποποιήσιμο, χωρίς να αλλάζει την παρατηρούμενη συμπεριφορά του. Αναδομώ (ρήμα): αναδιαρθρώνω ένα λογισμικό εφαρμόζοντας μια ακολουθία αναδομήσεων, χωρίς να αλλάζω την παρατηρούμενη συμπεριφορά του. 2.1.2 Χρησιμότητα της αναδόμησης Η διαδικασία της αναδόμησης κρίνεται σημαντική για τους εξής λόγους [8]: Βελτιώνει τη σχεδίαση του λογισμικού. Καθώς διαφορετικοί προγραμματιστές πραγματοποιούν αλλαγές για επίτευξη μικρών στόχων, για την οποία δεν απαιτείται πλήρης κατανόηση της σχεδίασης, σταδιακά χάνεται η δομή της σχεδίασης. Δημιουργούνται διπλότυπα, που αυξάνουν το μέγεθος του κώδικα, και τον καθιστούν δυσνόητο και δυσκολότερα τροποποιήσιμο, αφού η τροποποίηση πρέπει να γίνει σε όλα τα διπλότυπα. Μέσω της αναδόμησης, απαλείφονται τα διπλότυπα, καθιστώντας εμφανέστερη την σχεδίαση του λογισμικού. Βοηθά στην ταχύτερη συγγραφή κώδικα. Χωρίς αναδόμηση, σταδιακά χάνεται η αρχική δομή της σχεδίασης, ο κώδικας γίνεται δυσνόητος, δημιουργούνται σφάλματα λογισμικού (bugs). Ως αποτέλεσμα, η προσθήκη νέας λειτουργικότητας καθίσταται χρονοβόρα. Σε βάθος χρόνου η αναδόμηση εξοικονομεί χρόνο. Καθιστά το λογισμικό περισσότερο κατανοητό. Ως επί το πλείστον, το ίδιο λογισμικό συντηρείται και επεκτείνεται σε λειτουργικότητα από διαφορετικά άτομα. Επομένως είναι σημαντικό να διατηρείται κατανοητό. Ακόμα και αν ασχολείται το ίδιο άτομο με το λογισμικό, με την αναδόμηση παύει να ασχολείται με την απομνημόνευση της αντιστοίχισης λειτουργιών με τη θέση τους στον κώδικα. Επιπροσθέτως, μέσω της αναδόμησης καθίσταται κατανοητός ο κώδικας που συνέγραψε άλλος προγραμματιστής. Συνεισφέρει στον εντοπισμό σφαλμάτων λογισμικού (bugs). Καθώς το λογισμικό γίνεται πιο κατανοητό μέσω της αναδόμησης, ο εντοπισμός σφαλμάτων καθίσταται ευκολότερος. 12

2.1.3 Χρονική καταλληλότητα για εφαρμογή αναδόμησης Όταν χρησιμοποιείται η αναδόμηση ως μέθοδος ανάπτυξης λογισμικού, ο χρόνος κατανέμεται σε δύο δραστηριότητες: την προσθήκη λειτουργικότητας και την αναδόμηση. Όταν προστίθεται μια λειτουργία, δεν πρέπει να αλλάζει ο υφιστάμενος κώδικας (βάσει της αρχής Ανοιχτής-Κλειστής Σχεδίασης [9]). Όταν πραγματοποιείται αναδόμηση δεν προστίθεται λειτουργικότητα, απλώς αναδιαρθρώνεται ο κώδικας. 2.1.3.1 Πότε συνιστάται η διαδικασία της αναδόμησης Κανόνας των Τριών. Την δεύτερη φορά που γράφεται κάτι παρόμοιο, αναπόφευκτα εισάγονται διπλότυπα. Την τρίτη φορά που γράφεται κάτι παρόμοιο, τότε επιβάλεται αναδόμηση. Αναδόμηση όταν προστίθεται λειτουργικότητα. Αφενός, η αναδόμηση συνεισφέρει στην κατανόηση του κώδικα που πρέπει να τροποποιηθεί. Αφετέρου, συνδράμει στην ευκολότερη προσθήκη νέων λειτουργιών, μέσω βελτίωσης στον κώδικα της κακής σχεδίασης που καθιστούσε δύσκολη αυτή την προσθήκη. Αναδόμηση όταν απαιτείται διόρθωση ενός σφάλματος λογισμικού (bug). Η αναδόμηση καθιστά τον κώδικα κατανοητό και το σφάλμα γίνεται καλύτερα ορατό. Αναδόμηση κατά τη διάρκεια μιας Αναθεώρησης Κώδικα (Code Review). Οι αναθεωρήσεις κώδικα βοηθούν στην μετάδοση της γνώσης εντός μιας ομάδας ανάπτυξης. Συχνά οργανώνονται σε ομάδες των δύο, όπου ο ένας είναι ο συγγραφέας του κώδικα, ενώ ο άλλος προτείνει αλλαγές. Μαζί, συναποφασίζουν τις αλλαγές που μπορούν εύκολα να προστεθούν αφού γίνει πρώτα αναδόμηση του κώδικα για αυτό τον σκοπό. 2.1.3.2 Πότε δεν συνιστάται η διαδικασία της αναδόμησης Σε περιπτώσεις σχεδιαστικού λάθους. Πολλές φορές είναι εξαιρετικά δύσκολο ένα λάθος στη σχεδίαση να διορθωθεί μέσω αναδόμησης, αλλά κάποιες φορές είναι ευκολότερο. Για αυτό τον λόγο είναι προτιμότερο να δίνεται μεγαλύτερη βαρύτητα στην σχεδίαση, εκτός αν επιλεγεί η απλούστερη σχεδιαστική επιλογή που είναι εύκολο να αναδομηθεί στην άλλη εναλλακτική σχεδιαστική επιλογή. Όταν ο κώδικας πρέπει να γραφεί ξανά από την αρχή. Για παράδειγμα, όταν ο κώδικας περνώντας από τεστ βρεθεί γεμάτος σφάλματα και δεν μπορεί να σταθεροποιηθεί. Μια συμβιβαστική οδός είναι να αναδιαρθρωθεί μεγάλο τμήμα του κώδικα σε συστατικά με ισχυρή ενθυλάκωση. Με αυτό τον τρόπο, θα είναι δυνατό να ληφθεί η απόφαση για αναδόμηση ή εξαρχής ανακατασκευή ξεχωριστά για το κάθε συστατικό. 13

Όταν πλησιάζει η λήξη κάποιας προθεσμίας. Η αναδόμηση δεν θα προλάβει να αποφέρει κέρδος, αντιθέτως, αν δεν ολοκληρωθεί η εφαρμογή της μπορεί να περιπλέξει τον κώδικα. 2.1.4 Είδη αναδόμησης Ανάλογα με το αν η αναδόμηση αποτελείται από επιμέρους αναδομήσεις και αν χρησιμοποιεί υφιστάμενο κώδικα ή τον αντικαθιστά με άλλο, διακρίνονται τα εξής είδη αναδόμησης [16]: α) στοιχειώδης / χαμηλού επιπέδου αναδόμηση (low level refactoring). Πρόκειται για αναδόμηση που δεν αποτελείται από επιμέρους αναδομήσεις. Συνήθως αφορά σε μετακίνηση κώδικα. Για παράδειγμα, η Εξαγωγή Μεθόδου [8], [17] μετακινεί κώδικα σε νέα μέθοδο, ενώ η Μετακίνηση Μεθόδου [8], [18] μετακινεί μία μέθοδο από μία κλάση σε μία άλλη. β) σύνθετη αναδόμηση (composite refactoring). Είναι υψηλού επιπέδου αναδόμηση, η οποία συντίθεται από στοιχειώδεις αναδομήσεις. Η εφαρμογή της σύνθετης αναδόμησης ξεκινάει από ένα τμήμα κώδικα που χρειάζεται αλλαγή και εφαρμόζονται επαυξητικά στοιχειώδεις αναδομήσεις, μέχρι να επιτευχθεί μια επιθυμητή αλλαγή. Ανάμεσα στην εφαρμογή των στοιχειωδών αναδομήσεων εκτελούνται τεστ, προκειμένου να διασφαλισθεί ότι η παρατηρούμενη συμπεριφορά του κώδικα δεν άλλαξε. γ) αναδόμηση καθοδηγούμενη από τεστ (test-driven refactoring). Εμπεριέχει την εφαρμογή ανάπτυξης καθοδηγούμενης από τεστ (test-driven development) προκειμένου να συγγραφεί εκ νέου το τμήμα κώδικα, το οποίο αντικαθιστά το παλιό τμήμα κώδικα (διατηρώντας και επανεκτελώντας τα τεστ του παλιού κώδικα). Σύμωνα με τον Fowler [8], κάθε αναδόμηση έχει συγκεκριμένη μορφή, και αποτελείται από πέντε μέρη: 1) Όνομα (Name). Το όνομα είναι σημαντικό για την κατασκευή ενός λεξιλογίου αναδομήσεων. 2) Περίληψη (Summary). Περίληψη της περίπτωσης στην οποία χρειάζεται η συγκεκριμένη αναδόμηση και του τι κάνει η αναδόμηση. Αυτό το τμήμα βοηθά στην ταχύτερη εύρεση μιας αναδόμησης. 3) Κίνητρα (Motivation). Γιατί πρέπει να εφαρμοστεί η αναδόμηση και περιπτώσεις στις οποίες δεν πρέπει να εφαρμοστεί. 4) Αλγόριθμος (Mechanics). Συνοπτική, βήμα προς βήμα περιγραφή του τρόπου εφαρμογής της αναδόμησης. 14

5) Παραδείγματα (Examples). Παράθεση μιας πολύ απλής χρήσης της αναδόμησης, ούτως ώστε να διευκρινιστεί πώς λειτουργεί. Στο βιβλίο του, ο Fowler [8], παρουσιάζει 72 αναδομήσεις. Ενδεικτικά, παρατίθενται μερικές από αυτές στον Πίνακα 1. Τις κατηγοριοποιεί βάσει του κοινού σκοπού που υπηρετούν: Σύνθεση μεθόδων(composing methods). Σύνθεση μεθόδων προκειμένου να τακτοποιηθεί ο κώδικας καταλλήλως σε πακέτα. Οι μεγάλες μέθοδοι έχουν μεγάλο όγκο πληροφορίας που κρύβεται πίσω από την πολύπλοκη λογική. Μετακίνηση χαρακτηριστικών μεταξύ αντικειμένων (moving features between objects). Η (θεμελιώδης) απόφαση για την κατανομή των αρμοδιοτήτων ανάμεσα στα αντικείμενα. Οργάνωση δεδομένων (organizing data). Αναδομήσεις που απλοποιούν την εργασία με δεδομένα. Απλοποίηση υποθετικών εκφράσεων (simplifying conditional expressions). Απλοποίηση της υποθετικής λογικής, η οποία εγκυμονεί παγίδες. Απλοποίηση κλήσεων μεθόδου (making method calls simpler). Αναδομήσεις που καθιστούν τις διεπαφές κατανοητές και εύχρηστες. Ενασχόληση με την γενίκευση (dealing with generalization). Κυρίως αναδομήσεις που αφορούν στη μετακίνηση μεθόδων γύρω από μια ιεραρχία κληρονομικότητας. Μεγάλες αναδομήσεις (big refactorings). Αναδομήσεις πιο δύσκολες και χρονοβόρες, που αφορούν καθολικές αναδιαρθρώσεις, και δεν αντιμετωπίζονται από τις προηγούμενες κατηγορίες που αφορούν μεμονομένες κινήσεις αναδόμησης. Κατηγορία Αναδόμηση Composing Methods Extract Method Inline Method Inline Temp Moving Features Between Objects Move Field Move Method Extract Class Inline Class Hide Delegate Organizing Data Encapsulate Field Replace Data Value With Object Replace Type Code With Class 15

Simplifying Conditional Expressions Making Method Calls Simpler Dealing With Generalization Big Refactorings Πίνακας 1. Αναδομήσεις ανά κατηγορία, Fowler Replace Type Code With Subclasses Replace Type Code With State/Strategy Decompose Conditional Consolidate Duplicate Conditional Fragments Replace Conditional With Polymorphism Introduce Null Object Rename Method Replace Parameter With Method Replace Constructor With Factory Method Pull Up Method Form Template Method Extract Interface Replace Inheritance With Delegation Extract Hierarchy Convert Procedural Design To Objects Separate Domain From Presentation Tease Apart Inheritance 2.2 Πρότυπα Σχεδίασης 2.2.1 Ορισμός και τρόπος περιγραφής Προτύπων Σχεδίασης Στο ευρέως αναγνωρισμένο και αποδεκτό βιβλίο Design Patterns: Elements of Reusable Object Oriented Software [19], της συγγραφικής ομάδας που είναι γνωστή ως Gang of Four, δίνεται ο εξής ορισμός για τα πρότυπα σχεδίασης: «Τα Πρότυπα Σχεδίασης (Design Patterns) είναι περιγραφές αντικειμένων και κλάσεων που αλληλεπιδρούν, εξατομικευμένες ώστε να λύσουν ένα γενικό πρόβλημα σχεδίασης σε ένα ειδικότερο πλαίσιο.» Τα Πρότυπα Σχεδίασης δεν αφορούν δομές (όπως συνδεδεμένες λίστες - linked lists, πίνακες κατακερματισμού - hash tables ) που μπορούν να κωδικοποιηθούν σε κλάσεις και να χρησιμοποιηθούν όπως είναι. Ούτε είναι πολύπλοκα σχέδια συγκεκριμένου πεδίου εφαρμογής, για μια ολόκληρη εφαρμογή ή ένα υποσύστημα. Τα Πρότυπα Σχεδίασης διευκολύνουν την επαναχρησιμοποίηση επιτυχών σχεδίων και αρχιτεκτονικών. Βοηθούν στην επιλογή σχεδιαστικών εναλλακτικών που καθιστούν ένα σύστημα επαναχρησιμοποιήσιμο. 16

Βελτιώνουν την τεκμηρίωση και συντήρηση, υπογραμμίζοντας τις αλληλεπτιδράσεις κλάσεων και αντικειμένων, καθώς και τον σκοπό τους. Το όνομα κάθε προτύπου αρκεί για την επικοινωνία μιας σχεδιαστικής λύσης ανάμεσα σε μηχανικούς λογισμικού. Στο βιβλίο των Gang of Four [19] αναλύονται 23 πρότυπα σχεδίασης. Κάθε πρότυπο σχεδίασης περιγράφεται με τα εξής πεδία: Όνομα και Κατηγορία (Pattern Name and Classification). Το όνομα του προτύπου και μια κατηγοριοποίησή του. Σκοπός (Intent). Ο σκοπός του προτύπου και το πρόβλημα σχεδίασης που επιλύει. Συνώνυμα (Also Known As). Άλλα ονόματα με τα οποία είναι γνωστό το πρότυπο. Έναυσμα (Motivation). Ένα σενάριο που επιδεικνύει το πρόβλημα σχεδίασης που λύνει το πρότυπο. Εφαρμογή (Applicability). Περιγράφονται οι συνθήκες υπό τις οποίες είναι εφαρμόσιμο το πρότυπο. Δομή (Structure). Διάγραμμα κλάσεων ή/και ακολουθίας (class/sequence diagram) που αναπαριστά γραφικά το πρότυπο. Συμμετέχοντες (Participants). Οι κλάσεις και τα αντικείμενα που συμμετέχουν στο πρότυπο με τις αρμοδιότητές τους. Συνεργασίες (Collaborations). Ο τρόπος που συνεργάζονται οι συμμετέχοντες ώστε να ανταποκριθούν στις αρμοδιότητές τους. Συνέπειες (Consequences). Τα αποτελέσματα εφαρμογής του προτύπου. Υλοποίηση (Implementation). Οι τρόποι υλοποίησης του προτύπου. Κώδικας (Sample Code). Παραδείγματα κώδικα που δείχνουν την υλοποίηση του προτύπου. Γνωστές Χρήσεις (Known Uses). Η χρήση του προτύπου σε πραγματικά συστήματα λογισμικού. Συσχετιζόμενα Πρότυπα (Related Patterns). Άλλα πρότυπα σχεδίασης που έχουν στενή σχέση με το υπό εξέταση πρότυπο. 2.2.2 Κατηγοριοποίηση Προτύπων Σχεδίασης Τα 23 πρότυπα του βιβλίου των Gang of Four παρουσιάζονται στον Πίνακα 2. Ταξινομούνται βάσει των εξής δύο κριτηρίων: Σκοπός (purpose). Αντανακλά το τι κάνει το πρότυπο. Βάσει του σκοπού, διακρίνονται τρεις κατηγορίες προτύπων: i) Κατασκευαστικά πρότυπα (creational patterns). Ασχολούνται με την δημιουργία αντικειμένων. 17

ii) iii) Δομικά πρότυπα (structural patterns). Ασχολούνται με την σύνθεση κλάσεων ή αντικειμένων. Συμπεριφορικά πρότυπα (behavioral patterns). Ασχολούνται με τους τρόπους που οι κλάσεις ή τα αντικείμενα αλληλεπιδρούν και κατανέμουν αρμοδιότητες. Εμβέλεια (scope). Προσδιορίζει αν το πρότυπο εφαρμόζεται κυρίως σε κλάσεις ή σε αντικείμενα. Βάσει της εμβέλειας, διακρίνονται δύο κατηγορίες προτύπων: i) Πρότυπα κλάσης (class patterns). Αφορούν σε σχέσεις ανάμεσα σε κλάσεις και υποκλάσεις τους. Οι σχέσεις εγκαθιδρύονται μέσω κληρονομικότητας, επομένως είναι στατικές (static), δηλαδή καθορίζονται σε χρόνο μεταγλώττισης (compile time). ii) Πρότυπα αντικειμένου (object patterns). Αφορούν σε σχέσεις μεταξύ αντικειμένων, οι οποίες μπορούν να αλλάξουν σε χρόνο εκτέλεσης (run time), και είναι πιο δυναμικές (dynamic). Εμβέλει α Σκοπός Κατασκευαστικ ά Δομικά Συμπεριφορικά Κλάσης Factory Method Adapter Interpreter (Μέθοδος (Προσαρμογέας (Διερμηνέας) Εργοστάσιο) ) Template Method (Μέθοδος Υπόδειγμα) Αντικει - μένου Abstract Factory Adapter (Αφηρημένο (Προσαρμογέας Εργοστάσιο) ) Builder (Κτίστης) Bridge (Γέφυρα) Chain of Responsibility (Αλυσίδα Αρμοδιοτήτων) Command (Εντολή) Prototype (Πρωτότυπο) Singleton (Μοναδιαίο) Composite (Σύνθετο) Decorator (Διακοσμητής) Façade (Πρόσοψη) Iterator (Επαναλήπτης) Mediator (Μεσολαβητής) Memento (Υπόμνηση) 18

Proxy (Αντιπρόσωπος ) Flyweight Observer (Παρατηρητής) State (Κατάσταση) Strategy (Στρατηγική) Visitor (Επισκέπτης) Πίνακας 2. Ταξινόμηση των προτύπων σχεδίασης Πίνακας 3. Σχέσεις ανάμεσα στα πρότυπα σχεδίασης 19

Τα κατασκευαστικά πρότυπα κλάσης αναθέτουν τμήμα δημιουργίας αντικειμένων σε υποκλάσεις, ενώ τα κατασκευαστικά πρότυπα αντικειμένου το αναθέτουν σε άλλο αντικείμενο. Τα δομικά πρότυπα κλάσης χρησιμοποιούν κληρονομικότητα για σύνθεση κλάσεων, ενώ τα δομικά πρότυπα αντικειμένου περιγράφουν τρόπους συναρμολόγηση αντικειμένων. Τα συμπεριφορικά πρότυπα κλάσης χρησιμοποιούν κληρονομικότητα για περιγραφή αλγορίθμων και ροής ελέγχου, ενώ τα συμπεριφορικά πρότυπα αντικειμένου περιγράφουν πώς μια ομάδα αντικειμένων συνεργάζεται ώστε να εκτελέσει ένα έργο που κανένα αντικείμενο δεν μπορεί να εκτελέσει μόνο του. Ένας δεύτερος τρόπος οργάνωσης των προτύπων σχεδίασης είναι μέσω του πεδίου «Συσχετιζόμενα Πρότυπα». Οι σχέσεις ανάμεσα στα πρότυπα σχεδίασης απεικονίζονται στον Πίνακα 3. 2.2.3 Σχεδίαση για Αλλαγή Ένα σχέδιο που δεν λαμβάνει καθόλου υπόψιν του την αλλαγή, υφίσταται τον κίνδυνο σημαντικής ανασχεδίασης στο μέλλον. Βέβαια, όπως αναφέρει ο Fowler [1], μεγάλος βαθμός ευελιξίας στην σχεδίαση, συνεπάγεται αυξημένη πολυπλοκότητα, για αλλαγές που τελικά μπορεί να μη συμβούν. Σε τελική ανάλυση, το επίπεδο ευελιξίας που απαιτείται εξαρτάται από το είδος του λογισμικού. Όσο πιο επαναχρησιμοποιήσιμο και τυποποιημένο είναι, τόσο λιγότερες σχεδιαστικές αποφάσεις αφήνει στον απλό χρήστη, άρα πρέπει να έχει σχεδιαστεί με περισσότερη ευελιξία (πχ framework). Κάθε πρότυπο σχεδίασης επιτρέπει σε κάποιο χαρακτηριστικό της δομής του συστήματος να μεταβάλλεται ανεξάρτητα από άλλα χαρακτηριστικά, καθιστώντας το σύστημα περισσότερο εύρωστο σε ένα συγκεκριμένο είδος αλλαγής. Ακολουθούν συχνές περιπτώσεις ανασχεδίασης με τα πρότυπα σχεδίασης που τις αντιμετωπίζουν: 1. Δημιουργία ενός αντικειμένου προσδιορίζοντας ρητά μια κλάση. Ο προσδιορισμός ενός ονόματος κλάσης κατά τη δημιουργία ενός αντικειμένου δεσμεύει σε μια συγκεκριμένη υλοποίηση, αντί για μια συγκεκριμένη διεπαφή. Για αποφυγή του, συνιστάται η έμμεση δημιουργία αντικειμένων. Πρότυπα: Abstract Factory, Factory Method, Prototype. 2. Εξάρτηση από συγκεκριμένες λειτουργίες. Ο προσδιορισμός μιας συγκεκριμένης λειτουργίας, δεσμεύει για έναν μοναδικό τρόπο ικανοποίησης ενός αιτήματος. Αποφεύγοντας τέτοια αιτήματα, είναι ευκολότερη η αλλαγή του τρόπου ικανοποίησης ενός αιτήματος, τόσο σε χρόνο μεταγλώττισης, όσο και σε χρόνο εκτέλεσης. Πρότυπα: Chain of Responsibility, Command. 20

3. Εξάρτηση από πλατφόρμα υλικού και λογισμικού. Οι διεπαφές εξωτερικών λειτουργικών συστημάτων και οι διεπαφές προγραμματισμού εφαρμογών (APIs) διαφέρουν σε άλλες πλατφόρμες υλικού και λογισμικού. Λογισμικό που εξαρτάται από συγκεκριμένη πλατφόρμα δύσκολα μεταφέρεται σε άλλες πλατφόρμες. Μπορεί να είναι δύσκολο να διατηρηθεί ενήμερο ακόμη και στη δική του πλατφόρμα. Πρότυπα: Abstract Factory, Bridge. 4. Εξάρτηση από αναπαραστάσεις ή υλοποιήσεις αντικειμένων. Πελάτες που γνωρίζουν πώς ένα αντικείμενο αναπαρίσταται, αποθηκεύεται, εντοπίζεται, ή υλοποιείται, μπορεί να χρειαστούν τροποποίηση όταν το αντικείμενο αλλάξει. Η απόκρυψη αυτής της πληροφορίας από τους πελάτες συγκρατεί αυτή την μετάδοση της ανάγκης για αλλαγές. Πρότυπα: Abstract Factory, Bridge, Memento, Proxy. 5. Αλγοριθμικές εξαρτήσεις. Οι αλγόριθμοι συχνά επεκτείνονται, βελτιστοποιούνται, και αντικαθίστανται κατά την ανάπτυξη και επαναχρησιμοποίηση. Τα αντικείμενα που εξαρτώνται από έναν αλγόριθμο πρέπει να αλλάξουν όταν αλλάξει ο αλγόριθμος. Επομένως, οι αλγόριθμοι που είναι πιθανό να αλλάξουν συνιστάται να απομονώνονται. Πρότυπα: Builder, Iterator, Strategy, Template Method, Visitor. 6. Ισχυρή σύζευξη. Κλάσεις ισχυρά συζευγμένες είναι δύσκολο να επαναχρησιμοποιηθούν η καθεμιά ξεχωριστά. Η ισχυρή σύζευξη οδηγεί σε συστήματα όπου η αλλαγή ή μετακίνηση μιας κλάσης δεν είναι εφικτή χωρίς την κατανόηση και αλλαγή πολλών άλλων κλάσεων. Η χαλαρή σύζευξη αυξάνει την πιθανότητα μια κλάση να είναι επαναχρησιμοποιήσιμη από μόνη της και για ένα σύστημα να είναι ευκολότερη η εκμάθησή του, μεταφορά, τροποποίηση και επέκταση. Τα πρότυπα σχεδίασης χρησιμοποιούν τεχνικές όπως η αφηρημένη σύζευξη (abstract coupling) και ο διαχωρισμός σε στρώματα (layering) για προαγωγή των χαλαρά συζευγμένων συστημάτων. Πρότυπα: Abstract Factory, Bridge, Chain of Responsibility, Command, Facade, Mediator, Observer. 7. Επέκταση της λειτουργικότητας με υποκλάσεις. Η εξατομίκευση ενός αντικειμένου με δημιουργία υποκλάσεων συχνά είναι δύσκολη. Κάθε νέα κλάση έχει ένα σταθερό κόστος υλοποίησης (πχ αρχικοποίηση). Επίσης, ο ορισμός μιας υποκλάσης προϋποθέτει σε βάθος κατανόηση της γονεϊκής κλάσης. Για παράδειγμα, ο επαναορισμός μιας λειτουργίας ενδέχεται να επαναοριστεί κάποια άλλη. Μια επαναορισμένη λειτουργία μπορεί να πρέπει 21

να καλεί μια κληρονομημένη λειτουργία. Η δημιουργία υποκλάσεων μπορεί να οδηγήσει σε μια έκκρηξη κλάσεων, λόγω της ανάγκης εισαγωγής πολλών νέων υποκλάσεων ακόμη και για μια απλή επέκταση. Γενικά η σύνθεση αντικειμένων και ειδικά η ανάθεση ευθύνης (delegation) αποτελούν ευέλικτες εναλλακτικές αντί της κληρονομικότητας για τον συνδυασμό συμπεριφοράς. Νέα λειτουργικότητα μπορεί να προστεθεί σε μια εφαρμογή συνθέτοντας υφιστάμενα αντικείμενα με νέους τρόπους αντί για ορισμό νέων υποκλάσεων υφιστάμενων κλάσεων. Εντούτοις, έντονη χρήση της σύνθεσης αντικειμένων μπορεί να καταστήσει τη σχεδίαση δυσνόητη. Πολλά πρότυπα σχεδίασης παράγουν σχέδια στα οποία μπορεί να εισαχθεί εξατομικευμένη λειτουργικότητα απλώς ορίζοντας μια υποκλάση και συνθέτοντας στιγμιότυπά της με υφιστάμενα στιγμιότυπα. Πρότυπα: Bridge, Chain of Responsibility, Composite, Decorator, Observer, Strategy. 8. Αδύνατη η τροποποίηση κλάσεων με βολικό τρόπο. Ενίοτε απαιτείται τροποποίηση μιας κλάσης που δεν μπορεί να τροποποιηθεί βολικά. Μια περίπτωση είναι ο πηγαίος κώδικας να μην είναι διαθέσιμος (πχ μια εμπορική κλάση βιβλιοθήκης). Μια άλλη πιθανή περίπτωση είναι οποιαδήποτε αλλαγή να απαιτεί τροποποίηση αρκετών υφιστάμενων υποκλάσεων. Τα πρότυπα παρέχουν τρόπους τροποποίησης των κλάσεων σε τέτοιες περιπτώσεις. Πρότυπα: Adapter, Decorator, Visitor. 2.3 Αναδόμηση με Πρότυπα Όπως αναφέρει ο Fowler [1], ένα στυλ προγραμματισμού είναι το upfront design. Σε αυτό, η φάση της σχεδίασης θεωρείται εξαιρετικά σημαντική, διότι με καλή σχεδίαση αποφεύγεται σημαντικό κόστος αλλαγών και διορθώσεων. Ένα άλλο στυλ προγραμματισμού είναι αυτό της αναδόμησης. Σε αυτό το σενάριο, δεν γίνεται καθόλου σχεδιασμός. Απλώς κωδικοποιείται η πρώτη προσέγγιση που έρχεται στον νου, και μόλις φτάσει σε σημείο να είναι λειτουργική, εφαρμόζεται αναδόμηση ώστε να βελτιωθεί η μορφή της σχεδίασης σε επίπεδο κώδικα. Αυτό το προγραμματιστικό στυλ φέρεται ότι ακολουθούν οι υποστηρικτές του Extreme Programming [20]. Ακόμα και αυτοί όμως, κάνουν κάποιο σχέδιο πρώτα. Με τη λογική του upfront design η έμφαση δίνεται στη σχεδίαση, ώστε να αποφευχθούν αλλαγές στη σχεδίαση, οι οποίες κοστίζουν πολύ. Με την αναδόμηση, δεν γίνεται προσπάθεια να βρεθεί η βέλτιστη λύση στη σχεδίαση, απλώς μια λογική λύση. 22

Καθώς υλοποιείται η λύση, σταδιακά το πρόβλημα καθίσταται περισσότερο κατανοητό και διαφαίνεται καλύτερα η βέλτιστη λύση. Με την αναδόμηση όμως, οι αλλαγές κοστίζουν λιγότερο. Όπως προαναφέρθηκε, τα πρότυπα σχεδίασης αποτελούν αφηρημένες επαναχρησιμοποιήσιμες σχεδιαστικές λύσεις που μπορούν να εξατομικευτούν στο εκάστοτε πρόβλημα. Επίσης, η αναδόμηση αφορά στην αναδιάρθρωση του κώδικα χωρίς να αλλάξει η παρατηρούμενη συμπεριφορά του. Επομένως, με τη βοήθεια της κατηγοριοποίησης των προτύπων σχεδίασης και τις πληροφορίες στα πεδία τους (πχ ποιο πρόβλημα λύνουν, πότε μπορούν να εφαρμοστούν), μπορεί να γίνει ορατό ότι κάποιο πρότυπο σχεδίασης μπορεί να απλοποιήσει τη σχεδίαση. Άρα, μπορεί να γίνει προσπάθεια αναδόμησης σε αυτό το πρότυπο, αντί να εφαρμοστεί εξαρχής το πρότυπο και να αποδειχθεί στη συνέχεια ότι δε χρειαζόταν. Ο Kerievsky [16], παρουσιάζει 27 αναδομήσεις με στόχο πρότυπα (Πίνακας 4), στις οποίες χρησιμοποιούνται 19 από τα 23 πρότυπα σχεδίασης της ομάδας Gang of Four. Τις κατηγοριοποιεί σύμφωνα με την κατεύθυνση που ακολουθούν σε σχέση με το πρότυπο-στόχο σε: i) Αναδόμηση Σε ένα Πρότυπο (refactor To a pattern). Σε αυτό το είδος αναδόμησης, για να επιτευχθεί ο σκοπός της, πρέπει να υλοποιηθεί πλήρως το πρότυπο. Παράδειγμα: Compose Method. ii) Αναδόμηση Προς ένα Πρότυπο (refactor Towards a pattern). Σε αυτό το είδος αναδόμησης, για να επιτευχθεί ο σκοπός της, αρκεί να υλοποιηθούν ορισμένες από τις επιμέρους αναδομήσεις που αποτελούν την σύνθετη αναδόμηση. Παράδειγμα: Replace State Altering Conditionals with State. iii) Αναδόμηση Μακριά από ένα Πρότυπο (refactor Away from a pattern). Σε αυτή την περίπτωση αναδόμησης, για να επιτευχθεί ο σκοπός της, χρειάζεται να απομακρυνθεί το πρότυπο από τον κώδικα (Inline Singleton), ή να αντικατασταθεί από κάποιο άλλο (Move Accumulation to Visitor αντικαθιστά το πρότυπο Iterator με το πρότυπο Visitor). Pattern To Towards Away Adapter Extract Adapter, Unify Unify Interfaces Interfaces with Adapter with Adapter Builder Encapsulate Composite with Builder 23

Collecting Parameter Move Accumulation to Collecting Parameter Command Replace Conditional Dispatcher with Command Composed Compose Method Method Composite Replace One/Many Distinctions with Composite, Extract Composite, Replace Implicit Tree with Composite Creation Replace Constructors Method with Creation Methods Decorator Move Embellishment to Decorator Factory Move Creation Knowledge to Factory, Encapsulate Classes with Factory Factory Method Introduce Polymorphic Creation with Factory Method Interpreter Replace Implicit Language with Interpreter Iterator Null Object Introduce Null Object Replace Conditional Dispatcher with Command Move Embellishment to Decorator Encapsulate Composite with Builder Move Accumulation to Visitor 24

Observer Replace Hard-Coded Replace Hard- Notifications with Coded Observer Notifications with Observer Singleton Limit Instantiation with Singleton State Replace State-Altering Replace State- Conditionals with State Altering Conditionals with State Strategy Replace Conditional Replace Logic with Strategy Conditional Logic with Strategy Template Form Template Method Method Visitor Move Accumulation to Move Visitor Accumulation to Visitor Πίνακας 4. Πρότυπα και αναδομήσεις To, Towards, Away Inline Singleton 2.4 Αναδόμηση με απαλοιφή Κακών Οσμών Η αναδόμηση ή η βελτίωση της σχεδίασης του υφιστάμενου κώδικα προϋποθέτει τη γνώση του τμήματος κώδικα που χρειάζεται βελτίωση. Κοινά προβλήματα σχεδίασης εμφανίζονται σε κώδικα που: α) εμφανίζει διπλότυπα, β) είναι ασαφής, γ) περίπλοκος. Αυτή η λίστα κοινών προβλημάτων σχεδίασης είναι ασαφής, για αυτό τον λόγο οι Fowler και Beck [8], παρέχουν επιπλέον καθοδήγηση. Παρομοιάζουν τα σχεδιαστικά προβλήματα με Κακές Οσμές (Bad Smells), και εξηγούν ποιες αναδομήσεις ή συνδυασμοί τους είναι πιο αποτελεσματικοί στην απαλοιφή των Κακών Οσμών. Από τις 22 Κακές Οσμές που αναλύουν οι Fowler και Beck [8], καθώς και τις 5 νέες που ανακάλυψε, ο Kerievsky συνδέει τις 12 με αναδομήσεις που τις απαλείφουν. Ο Πίνακας 5 περιγράφει τις 27 συνολικά Κακές Οσμές και τις αναδομήσεις για την απαλοιφή τους, από τα βιβλία των Fowler [8], Kerievsky [16]. 25

Πίνακας 5. Κακές Οσμές και Αναδομήσεις για την απαλοιφή τους, από τα βιβλία F: Fowler - Refactoring: Improving the Design of Existing Code", K: Kerievsky Refactoring to Patterns. Πηγή: http://industriallogic.com, Κατόπιν Επεξεργασίας. Κακή Οσμή Alternative Classes with Different Interfaces: Παρόμοιες κλάσεις με διαφορετικές διεπαφές. Βρίκοντας τις ομοιότητες, μπορούν να αναδομηθούν ώστε να έχουν κοινή διεπαφή. Combinatorial Explosion: Πολλά τμήματα κώδικα κάνουν το ίδιο με άλλους συνδυασμούς δεδομένων ή συμπεριφοράς. Comments (ή Deodorant): Όταν γίνεται αισθητή η ανάγκη συγγραφής σχολίου, πρώτα προσπάθεια αναδόμησης ώστε το σχόλιο να καταστεί περιττό. Conditional Complexity: Η υποθετική λογική αρχικά είναι κατανοητή όσο περιέχεται σε λίγες γραμμές κώδικα. Με προσθήκη μερικών νέων χαρακτηριστικών, ξαφνικά γίνεται περίπλοκη και εκτεταμένη. Data Class: Κλάσεις που έχουν μόνο πεδία και μεθόδους set/get για αυτά. Τέτοιες κλάσεις απλώς κρατούν δεδομένα, ενώ συχνά ο χειρισμός τους γίνεται λεπτομερέστερα από άλλες κλάσεις. Data Clumps: Ομάδες δεδομένων που εμφανίζονται σε διάφορα σημεία μαζί πρέπει να τοποθετηθούν σε ξεχωριστό αντικείμενο. Ένα καλό τεστ: αν διαγραφεί μια τιμή από τα δεδομένα, οι άλλες θα βγάζουν νόημα; Αν όχι, τότε σίγουρα πρέπει να δημιουργηθεί νέο αντικείμενο. Αναδόμηση Unify Interfaces with Adapter [K 247] Rename Method [F 273] Move Method [F 142] Replace Implicit Language with Interpreter [K 269] Rename Method [F 273] Extract Method [F 110] Introduce Assertion [F 267] Introduce Null Object [F 260, K 301] Move Embellishment to Decorator [K 144] Replace Conditional Logic with Strategy [K 129] Replace State-Altering Conditionals with State [K 166] Move Method [F 142] Encapsulate Field [F 206] Encapsulate Collection [F 208] Extract Class [F 149] Preserve Whole Object [F 288] Introduce Parameter Object [F 295] 26

Divergent Change: Παρατηρείται όταν μια κλάση αλλάζει συχνά με διαφορετικούς τρόπους για διαφορετικούς λόγους. Ο διαχωρισμός των αποκλινουσών αρμοδιοτήτων μειώνει την πιθανότητα μια αλλαγή να επηρεάσει μια άλλη, και ελαττώνει το κόστος συντήρησης. Duplicated Code: Ο Διπλότυπος κώδικας είναι η πιο διεισδυτική και ενοχλητική οσμή. Εμφανίζεται είτε ως πανομοιότυπος κώδικας, ή ως δομές/βήματα επεξεργασίας εξωτερικά διαφορετικά, αλλά ουσιαστικά ίδια. Feature Envy: Τα δεδομένα και οι λειτουργίες πάνω σε αυτά πηγαίνουν μαζί. Όταν μια μέθοδος κάνει πολλές κλήσεις σε άλλες κλάσεις ώστε να αποκτήσει δεδομένα ή λειτουργικότητα, τότε υφίσταται Feature Envy. Freeloader (ή Lazy Class): Μια κλάση που δεν κάνει αρκετά ώστε να αξίζει η συντήρησή της πρέπει να απαλείφεται. Extract Class [F 149] Chain Constructors [K 340] Extract Composite [K 214] Extract Method [F 110] Extract Class [F 149] Form Template Method [F 345, K 205] Introduce Null Object [F 260, K 301] Introduce Polymorphic Creation with Factory Method [K 88] Pull Up Method [F 322] Pull Up Field [F 320] Replace One/Many Distinctions with Composite [K 224] Substitue Algorithm [F 139] Unify Interfaces with Adapter [K 247] Extract Method [F 110] Move Method [F 142] Move Field [F 146] Collapse Hierarchy [F 344] Inline Class [F 154] Inline Singleton [K 114] Move Method [F 142] 27

Inappropriate Intimacy: Οι κλάσεις γίνονται υπερβολικά "οικείες" μεταξύ τους, και σπαταλούν πολύ χρόνο προσπελαύνοντας η μια τα ιδιωτικά (private) τμήματα της άλλης. Υπερβολικά "οικείες" κλάσεις πρέπει να αποσυνδέονται. Incomplete Library Class: Εμφανίζονται στον κώδικα αρμοδιότητες που ξεκάθαρα πρέπει να μετακινηθούν σε κλάση βιβλιοθήκης, όμως είναι ανέφικτη ή ασύμφορη η τροποποίηση της κλάσης βιβλιοθήκης ώστε να δεχθεί αυτές τις νέες αρμοδιότητες. Indecent Exposure: Απουσία ενθυλάκωσης πληροφορίας. Είναι ορατές σε πελάτες μέθοδοι/κλάσεις που δεν πρέπει. Περιπλέκει τη σχεδίαση. Large Class: Η παρουσία υπερβολικά πολλών μεταβλητών στιγμιοτύπου συχνά αποτελεί ένδειξη ότι μια κλάση προσπαθεί να κάνει υπερβολικά πολλά. Οι μεγάλες κλάσεις συνήθως έχουν περισσότερες αρμοδιότητες από όσες θα έπρεπε. Move Field [F 146] Change Bidirectional Association to Unidirectional Association [F 200] Extract Class [F 149] Hide Delegate [F 157] Replace Inheritance with Delegation [F 352] Introduce Foreign Method [F 162] Introduce Local Extension [F 164] Encapsulate Classes with Factory [K 80] Extract Class [F 149] Extract Subclass [F 330] Extract Interface [F 341] Replace Data Value with Object [F 175] Replace Conditional Dispatcher with Command [K 191] Replace Implicit Language with Interpreter [K 269] Replace State-Altering Conditionals with State [K 166] Extract Method [F 110] Compose Method [K 123] 28

Long Method: Δύο εκτενείς μέθοδοι είναι πιθανό να περιέχουν διπλότυπο κώδικα. Οι μικρές μέθοδοι συμβάλλουν στην κατανοησιμότητα, συντηρησιμότητα και επεκτασιμότητα του λογισμικού. Long Parameter List: Οι εκτενείς λίστες παραμέτρων σε μια μέθοδο είναι δυσνόητες και αλλάζουν όποτε χρειάζονται πρόσθετα δεδομένα. Σημασία έχει ποια αντικείμενα χρειάζεται πραγματικά η μέθοδος για να επιτελέσει το έργο της. Message Chains: Παρατηρείται χρήση μεγάλων ακολουθιών κλήσεων μεθόδων ή προσωρινών μεταβλητών, προκειμένου να επιστραφούν δεδομένα. Αυτή η αλυσίδα δημιουργεί εξάρτηση από τις σχέσεις ανάμεσα σε ενδεχομένως ασυσχέτιστα αντικείμενα. Introduce Parameter Object [F 295] Move Accumulation to Collecting Parameter [K 313] Move Accumulation to Visitor [K 320] Decompose Conditional [F 238] Preserve Whole Object [F 288] Replace Conditional Dispatcher with Command [K 191] Replace Conditional Logic with Strategy [K 129] Replace Method with Method Object [F 135] Replace Temp with Query [F 120] Replace Parameter with Method [F 292] Introduce Parameter Object [F 295] Preserve Whole Object [F 288] Hide Delegate [F 157] Extract Method [F 110] Move Method [F 142] Remove Middle Man [F 160] Inline Method [F 117] 29

Middle Man: Το delegation (ανάθεση αρμοδιοτήτων) είναι σημαντικό χαρακτηριστικό των αντικειμένων. Όμως, κατάχρησή του οδηγεί σε αντικείμενα που δεν προσθέτουν αξία, απλώς αποστέλλουν μηνύματα σε άλλα αντικείμενα. Oddball Solution: Όταν ένα πρόβλημα επιλύεται με δύο τρόπους στο ίδιο σύστημα, τότε μια λύση είναι ασυνεπής. Συνήθης ένδειξη λιγότερο εμφανούς διπλότυπου κώδικα. Parallel Inheritance Hierarchies: Ειδική περίπτωση του Shotgun Surgery - όποτε δημιουργείται υποκλάση μιας κλάσης, απαιτείται δημιουργία υποκλάσης μιας άλλης κλάσης. Primitive Obsession: Συχνά, οι κλάσεις παρέχουν έναν απλούστερο και πιο φυσικό τρόπο μοντελοποίησης εννοιών από τους πρωταρχικούς τύπους (int,double,...). Επίσης, συχνά παρατηρείται μετά τη δημιουργία μιας κλάσης ότι άλλος κώδικας στο σύστημα ανήκει σε αυτή. Η υπερβολική εξάρτηση από πρωταρχικούς τύπους, παρατηρείται συνήθως όταν δεν έχει ειδωθεί μια υψηλότερου επιπέδου αφαίρεση που μπορεί να αποσαφηνίσει ή να απλοποιήσει τον κώδικα. Replace Delegation with Inheritance [F 355] Unify Interfaces with Adapter [K 247] Move Method [F 142] Move Field [F 146] Replace Data Value with Object [F 175] Encapsulate Composite with Builder [K 96] Introduce Parameter Object [F 295] Extract Class [F 149] Move Embellishment to Decorator [K 144] Replace Conditional Logic with Strategy [K 129] Replace Implicit Language with Interpreter [K 269] Replace Implicit Tree with Composite [K 178] Replace State-Altering Conditionals with State [K 166] Replace Type Code with Class [F 218, K 286] 30

Refused Bequest: Μη επιθυμητή κληρονόμηση κώδικα. Λύση δίνεται μέσω κώδικα που αρνείται το κληροδότημα, κρατώντας από αυτό μόνο τα ωφέλιμα χαρακτηριστικά. Shotgun Surgery: Απαιτείται αλλαγή αρκετού κώδικα σε διαφορετικά σημεία, απλώς για προσθήκη νέας ή επεκτείνουσας συμπεριφοράς. Solution Sprawl: Κώδικας ή/και δεδομένα που χρησιμοποιούνται για εκτέλεση μιας αρμοδιότητας εξαπλώνονται σε πολλές κλάσεις. Συχνά οφείλεται στην βιαστική προσθήκη ενός χαρακτηριστικού σε κάποιο σύστημα, χωρίς αφιέρωση χρόνου πρώτα στην απλοποίηση και σταθεροποίηση της σχεδίασης ώστε να υποδεχθεί καλύτερα το χαρακτηριστικό. Speculative Generality: Γενικός/Αφηρημένος κώδικας που δεν χρειάζεται σήμερα και ενδεχομένως ούτε στο μέλλον. Εντοπίζεται αν οι μόνοι χρήστες μιας μεθόδου/κλάσης είναι περιπτώσεις ελέγχου, εκτός αν η μέθοδος/κλάση είναι βοηθητική σε περίπτωση ελέγχου χρήσιμης λειτουργικότητας. Switch Statement: Υφίστανται διπλότυπα ενός switch/if statement. Κάθε νέα περίπτωση πρέπει να προστεθεί σε όλα τα διπλότυπα του statement. Συνήθως αντικαθίσταται από πολυμορφισμό. Replace Type Code with State/Strategy [F 227] Replace Type Code with Subclasses [F 223] Replace Array With Object [F 186] Push Down Field [F 329] Push Down Method [F 322] Replace Inheritance with Delegation [F 352] Move Method [F 142] Move Field [F 146] Inline Class [F 154] Move Creation Knowledge to Factory [K 68] Collapse Hierarchy [F 344] Rename Method [F 273] Remove Parameter [F 277] Inline Class [F 154] Move Accumulation to Visitor [K 320] Replace Conditional Dispatcher with Command [K 191] 31

Temporary Field: Τα αντικείμενα ενίοτε περιέχουν πεδία που δε χρειάζονται καθόλη τη ζωή των αντικειμένων. Τον υπόλοιπο χρόνο, το πεδίο είναι άδειο ή περιέχει άσχετα δεδομένα, κάτι που είναι δύσκολα κατανοητό. Συχνά, αποτελεί μια κακή εναλλακτική στη δημιουργία Εκτενούς Λίστας Παραμέτρων. Replace Conditional with Polymorphism [F 255] Replace Type Code with Subclasses [F 223] Replace Type Code with State/Strategy [F 227] Replace Parameter with Explicit Methods [F 285] Introduce Null Object [F 260, K 301] Extract Class [F 149] Introduce Null Object [F 260, K 301] 32

3. Πρότυπο Επισκέπτης 3.1 Παρουσίαση Προτύπου Επισκέπτης Το πρότυπο σχεδίασης Επισκέπτης (Visitor), βάσει του κριτηρίου της εμβέλειας, ανήκει στα Πρότυπα Αντικειμένου (Object Patterns). Με άλλα λόγια, αφορά σε σχέσεις μεταξύ αντικειμένων, οι οποίες μπορούν να αλλάξουν σε χρόνο εκτέλεσης (run time). Επίσης, σύμφωνα με το κριτήριο του σκοπού, ανήκει στα Συμπεριφορικά Πρότυπα (Behavioral Patterns). Ασχολείται δηλαδή με τους τρόπους που οι κλάσεις ή τα αντικείμενα αλληλεπιδρούν και κατανέμουν αρμοδιότητες. Σκοπός του είναι η αναπαράσταση μιας λειτουργίας που πρόκειται να εφαρμοστεί στα στοιχεία μιας δομής αντικειμένων. Το πρότυπο Επισκέπτης επιτρέπει τον ορισμό μιας νέας λειτουργίας χωρίς τροποποίηση των κλάσεων των στοιχείων στα οποία θα εφαρμοστεί αυτή η λειτουργία. Εφαρμογή. Συνιστάται η εφαρμογή του προτύπου Επισκέπτης όταν: - μια δομή αντικειμένων περιέχει πολλές κλάσεις αντικειμένων με διαφορετικές διεπαφές, και απαιτείται εκτέλεση λειτουργιών σε αυτά τα αντικείμενα που εξαρτάται από τις συγκεκριμένες (concrete) κλάσεις τους. - απαιτείται εφαρμογή πολλών μη σχετιζόμενων λειτουργιών σε αντικείμενα μιας δομής αντικειμένων, και είναι ενοχλητική η «μόλυνση» των κλάσεών τους με αυτές τις λειτουργίες. Το πρότυπο Επισκέπτης διατηρεί τις σχετιζόμενες λειτουργίες μαζί, ορίζοντάς τις σε μία κλάση. Όταν η δομή αντικειμένων χρησιμοποιείται από πολλές εφαρμογές, το πρότυπο Επισκέπτης τοποθετεί τις λειτουργίες μόνο στις εφαρμογές που τις χρειάζονται. Με άλλα λόγια, το πρότυπο διαχωρίζει τη συμπεριφορά (λειτουργίεςμεθόδους) από την κατάσταση (τιμές ιδιοτήτων). - οι κλάσεις που ορίζουν την δομή αντικειμένων αλλάζουν σπανίως, όμως συχνά απαιτείται ορισμός νέων λειτουργιών στην δομή. Η τροποποίηση των κλάσεων της δομής αντικειμένων προϋποθέτει επαναορισμό της διεπαφής σε όλους τους συγκεκριμένους επισκέπτες (concrete visitors). Αν οι κλάσεις της δομής αντικειμένων αλλάζουν συχνά, είναι προτιμότερος ο ορισμός των λειτουργιών σε αυτές τις κλάσεις. 33

Εικόνα 1. Δομή Προτύπου Επισκέπτης Εικόνα 2. Συνεργασίες αντικειμένων στο πρότυπο Επισκέπτης Συμμετέχοντες. Ακολουθούν τα στοιχεία από τα οποία δομείται το πρότυπο (Εικόνα 1): Visitor: ορίζει μια λειτουργία Visit για κάθε κλάση ConcreteElement της ObjectStructure. Το όνομα και η υπογραφή της λειτουργίας, ταυτοποιούν την κλάση (ConcreteElement) που στέλνει το αίτημα Visit στη διεπαφή (interface) Visitor. Αυτό επιτρέπει στον visitor να προσδιορίσει την (concrete) κλάση του στοιχείου (ConcreteElement) το οποίο επισκέπτεται ο Visitor. 34