Περίληψη : | Η ανάγκη διασφάλισης της μακροβιότητας και της ανταγωνιστικότητας των σύγχρονων συστημάτων λογισμικού έχει οδηγήσει στην υιοθέτηση της μεθοδολογίας της εξελικτικής ανάπτυξης λογισμικού, σύμφωνα με την οποία το λογισμικό εξελίσσεται καθ’ όλη τη διάρκεια του κύκλου ζωής του, ακόμη και μετά την παράδοσή του. Ωστόσο, οι συνεχείς τροποποιήσεις στις οποίες υπόκειται ένα σύστημα λογισμικού δύνανται να οδηγήσουν σε βαθμιαία υποβάθμιση της ποιότητας της σχεδίασής του. Προς την κατεύθυνση της βελτίωσης της ποιότητας σχεδίασης του λογισμικού στοχεύει η μεθοδολογία της αναδόμησης με πρότυπα σχεδίασης, η οποία και αποτελεί κύρια πρακτική της εξελικτικής σχεδίασης. Η αναδόμηση είναι η διαδικασία εφαρμογής μικρών και τυποποιημένων μετασχηματισμών στην εσωτερική δομή του λογισμικού, με σκοπό τη βελτίωση ορισμένων ποιοτικών χαρακτηριστικών του και με τρόπο που να μη μεταβάλλεται η εξωτερικά παρατηρήσιμη συμπεριφορά του. Τα πρότυπα σχεδίασης, από την άλλη, αποτελούν ευρέως αποδεκτές, έτοιμες ή σχεδόν έτοιμες υψηλού επιπέδου σχεδιαστικές λύσεις σε κοινά επαναλαμβανόμενα προβλήματα σχεδίασης. Η πρακτική της αναδόμησης με πρότυπα σχεδίασης επιχειρεί να συνδυάσει τα οφέλη από την εφαρμογή μιας αναδόμησης με τα πλεονεκτήματα των προτύπων σχεδίασης, με απώτερο σκοπό τη βελτίωση της ποιότητας σχεδίασης ενός συστήματος λογισμικού. Ωστόσο, η αναδόμηση είναι μια ιδιαίτερα απαιτητική διαδικασία, τόσο αναφορικά με την απαιτούμενη προσπάθεια, όσο και σχετικά με το χρόνο που πρέπει να δαπανηθεί ώστε να πραγματοποιηθεί με ασφάλεια, χωρίς την εισαγωγή σφαλμάτων και διασφαλίζοντας τη διατήρηση της αρχικής συμπεριφοράς του λογισμικού. Οι απαιτήσεις αυτές σε συνδυασμό με το διαρκώς αυξανόμενο μέγεθος των σύγχρονων συστημάτων λογισμικού καθιστούν δύσκολη τη χειρωνακτική διενέργειά της από τους μηχανικούς λογισμικού. Η αξία της αυτοματοποίησης της διαδικασίας της αναδόμησης έχει επιβεβαιωθεί από τη βιομηχανία λογισμικού και πληθώρα εργαλείων αυτόματης αναδόμησης έχει αναπτυχθεί. Ωστόσο, η πλειοψηφία των εργαλείων αυτόματης αναδόμησης υποστηρίζει μόνο απλές αναδομήσεις χαμηλού επιπέδου, χωρίς να παρέχει τη δυνατότητα αυτοματοποιημένης εκτέλεσης πιο σύνθετων αναδομήσεων, όπως οι αναδομήσεις που αποσκοπούν στην εισαγωγή κάποιου σχεδιαστικού προτύπου. Την έλλειψη αυτή προτίθεται να μειώσει η παρούσα διπλωματική εργασία, η οποία και μελετά το πρόβλημα της αυτοματοποίησης της αναδόμησης προς το σχεδιαστικό πρότυπο Null Αντικείμενο (Null Object). Το πρότυπο Null Object, βασιζόμενο στις αρχές της κληρονομικότητας και του πολυμορφισμού, ενδείκνυται να χρησιμοποιηθεί στις περιπτώσεις όπου υπάρχουν στον κώδικα επαναλαμβανόμενοι έλεγχοι αν ένα αντικείμενο είναι διάφορο του null προτού σταλεί ένα μήνυμα σε αυτό. Στόχος της μεθοδολογίας που αναπτύχθηκε είναι η αυτοματοποιημένη ανίχνευση περιπτώσεων που είναι δυνατή η εφαρμογή του προτύπου Null Object. Επιπλέον, η προτεινόμενη προσέγγιση επιτρέπει, για τις περιπτώσεις που πληρούν τα κριτήρια αυτόματης εφαρμογής της αναδόμησης, και την αυτοματοποιημένη ανασύνταξη του πηγαίου κώδικα ώστε να εφαρμοστεί η δομή του προτύπου. Πιο συγκεκριμένα, η προτεινόμενη μεθοδολογία περιορίζεται στην ανίχνευση και απομάκρυνση υποθετικής λογικής που ελέγχει αν ένα πεδίο είναι ίσο ή όχι με null προτού καλέσει κάποια μέθοδο αυτού, ώστε να αποφευχθεί η πρόκληση Null Pointer Exception, μιας και o προγραμματιστής δεν είναι σίγουρος αν στο πεδίο έχει τεθεί τιμή διάφορη του null. Προκειμένου να οριοθετηθεί το πρόβλημα της ανίχνευσης των περιπτώσεων αναδόμησης προς το πρότυπο Null Object, η προτεινόμενη μεθοδολογία ανίχνευσης, αρχικά προσπαθεί να εντοπίσει σε κάθε κλάση του υπό εξέταση κώδικα εκείνα τα πεδία της που είναι τύπου κάποιας κλάσης του υπό εξέταση συστήματος, ώστε να είναι δυνατή η εφαρμογή της αναδόμησης. Τα πεδία αυτά στη συνέχεια εξετάζονται για να εξακριβωθεί αν ικανοποιούν ένα σύνολο επιλεγμένων κριτηρίων που υποδηλώνουν ότι υπάρχει μεγάλη πιθανότητα στην κλάση όπου ορίζονται να υπάρχουν υποθετικές εκφράσεις που ελέγχουν αν η τιμή τους ισούται ή όχι με null. Κάθε πεδίο που ικανοποιεί τα κριτήρια της προηγούμενης ανάλυσης χαρακτηρίζεται ως υποψήφιο για την εφαρμογή της αναδόμησης προς το πρότυπο Null Object. Στη συνέχεια εξετάζεται κατά πόσο υπάρχουν υποθετικές δηλώσεις που ελέγχουν αν το πεδίο είναι ίσο ή διάφορο του null και οι οποίες πληρούν ένα σύνολο κριτηρίων που καθιστούν δυνατή τη διαγραφή τους, εξασφαλίζοντας παράλληλα τη μη εισαγωγή σφαλμάτων και τη διατήρηση της συμπεριφοράς του λογισμικού. Μόνο τα πεδία για τα οποία θα ανιχνευτούν υποθετικές δηλώσεις υποψήφιες για διαγραφή θα θεωρηθούν τελικά κατάλληλα για την εφαρμογή της αναδόμησης προς το πρότυπο Null Object, μιας και μόνο τότε θα έχουμε όφελος από τη χρήση του προτύπου. Επιπλέον, ένα τρίτο σύνολο κριτηρίων εξετάζεται ώστε να αποφανθούμε αν για τα κατάλληλα πεδία δύναται να αυτοματοποιηθεί η εφαρμογή της αναδόμησης προς το πρότυπο Null Object. Σε διαφορετική περίπτωση, η προτεινόμενη μεθοδολογία θα κατατάσσει αυτό το πεδίο ως suggested refactorable, μιας και απαιτείται η επέμβαση του προγραμματιστή για την εφαρμογή της αναδόμησης προς το πρότυπο Null Object. Αναφορικά με την υλοποίηση της αυτόματης ανίχνευσης υποψήφιων περιπτώσεων αναδόμησης προς το πρότυπο Null Object, η προτεινόμενη μεθοδολογία βασίστηκε στην τεχνική της στατικής ανάλυσης (static analysis) του πηγαίου κώδικα, ώστε να παραχθεί ως κύρια μορφή αναπαράστασής του το Αφηρημένο Συντακτικό Δέντρο (Abstract Syntax Tree, AST). Το AST δέντρο αναλύεται ώστε να εντοπιστούν τα πεδία και οι υποθετικές δομές που ικανοποιούν τις προϋποθέσεις που ορίζονται από τη μεθοδολογία, ενώ για ένα συγκεκριμένο υποσύνολο των κριτηρίων ανίχνευσης, που οι απαιτούμενες πληροφορίες δεν ήταν δυνατό να εξαχθούν από αυτό, χρησιμοποιήθηκε τόσο ο Γράφος Ροής Ελέγχου (Control Flow Graph, CFG) όσο και ο Γράφος Εξαρτήσεων Προγράμματος (Program Dependence Graph, PDG). Οι προτάσεις αναδόμησης που προκύπτουν ως αποτέλεσμα της διαδικασίας ανίχνευσης και εμφανίζονται στον χρήστη, αντιστοιχούν στις υποθετικές δηλώσεις που η έκφρασή τους ελέγχει την τιμή κάποιου υποψήφιου για αναδόμηση πεδίου. Οι προτάσεις αυτές εμφανίζονται στο χρήστη ταξινομημένες ανάλογα με το αν μπορούν να διαγραφούν και ομαδοποιημένες ανά υποψήφιο πεδίο. Ακολούθως, ο χρήστης δύναται να επιθεωρήσει τις προτάσεις αναδόμησης μία προς μία και να επιλέξει εκείνες που επιθυμεί να εκτελέσει. Κατά την εφαρμογή της επιλεγμένης από το χρήστη πρότασης αναδόμησης, το αφηρημένο συντακτικό δέντρο του υπό εξέταση κώδικα ανασυντάσσεται και παρέχεται στο χρήστη η δυνατότητα προεπισκόπησης της προτεινόμενης αναδόμησης προτού επιλέξει την εφαρμογή της, καθώς και η δυνατότητα απόρριψής της. Όταν ο χρήστης επιβεβαιώσει την εφαρμογή της προτεινόμενης αναδόμησης, οι μετασχηματισμοί του AST δέντρου χρησιμοποιούνται ώστε να τροποποιηθεί ο πηγαίος κώδικας του λογισμικού χωρίς την παρέμβαση του χρήστη. Κατά την εφαρμογή μιας αναδόμησης με χρήση του προτύπου Null Object, οι μετασχηματισμοί που εφαρμόζονται στο AST δέντρο αποσκοπούν στην υλοποίηση των δομικών στοιχείων του προτύπου στο αναδομούμενο σύστημα, καθώς και στην εξασφάλιση της διατήρησης της αρχικής συμπεριφοράς του υπό εξέταση συστήματος. Τα δομικά στοιχεία από τα οποία αποτελείται το πρότυπο Null Object, όταν ακολουθείται η προσέγγιση δημιουργίας αφηρημένης υπερκλάσης, είναι η κλάση πελάτης που δηλώνει το υποψήφιο πεδίο, το πεδίο για το οποίο διαγράφονται οι υποθετικοί έλεγχοι, η αφηρημένη κλάση και οι συγκεκριμένες υποκλάσεις της. Κατά συνέπεια, οι εκτελούμενοι μετασχηματισμοί της αναδόμησης, συνοψίζονται στην δημιουργία της αφηρημένης κλάσης και της συγκεκριμένης Null Object υποκλάσης της, οι μέθοδοι της οποίας θα έχουν την κατάλληλη συμπεριφορά ώστε να είναι δυνατή η διαγραφή όσο το δυνατόν περισσότερων υποθετικών δηλώσεων από το πρόγραμμα. Επιπλέον, το επιλεγμένο πεδίο θα πρέπει να δηλωθεί με τύπο την αφηρημένη υπερκλάση και να αρχικοποιηθεί με ένα στιγμιότυπο της Null Object υποκλάσης. Τέλος, η κλάση πελάτης πρέπει να τροποποιηθεί καταλλήλως, ώστε να διαγραφούν οι υποθετικές δηλώσεις που δύναται να διαγραφούν, αλλά και να διατηρηθεί ίδια η συμπεριφορά του λογισμικού. Η προτεινόμενη μεθοδολογία υλοποιήθηκε με χρήση της γλώσσας προγραμματισμού Java και των βιβλιοθηκών JDT και LTK του Eclipse και ενσωματώθηκε σαν τμήμα του υπάρχοντος εργαλείου αναδόμησης του Eclipse IDE, JDeodorant. Το εργαλείο JDeodorant, στο οποίο και στηρίχτηκε η υλοποίηση της προτεινόμενης μεθοδολογίας, είναι ένα plug-in του Eclipse που παρέχει τη δυνατότητα εκτέλεσης αναδομήσεων που επιλύουν τα σχεδιαστικά προβλήματα «God Class», «Long Method», «Type Checking» και «Feature Envy». Μετά την ολοκλήρωση της υλοποίησης του σχετικού υποστηρικτικού εργαλείου, η προτεινόμενη μεθοδολογία δοκιμάστηκε σε διάφορα συστήματα λογισμικού ανοιχτού κώδικα, προκειμένου να αξιολογηθεί η αποτελεσματικότητα της τόσο αναφορικά με τη χρησιμότητα και την εφαρμοσιμότητά της στην πράξη όσο και ως προς την κλιμακωσιμότητά της. Ιδιαίτερη μέριμνα δόθηκε ώστε τα συστήματα λογισμικού που χρησιμοποιήθηκαν κατά την πειραματική αξιολόγηση να είναι αρκετά σε πλήθος και μεγάλα από άποψη μεγέθους και συνθετότητας. Η απόφαση αυτή πάρθηκε για λόγους πληρότητας, ώστε η χρησιμότητα αλλά και η κλιμακωσιμότητα της μεθοδολογίας να εξεταστεί σε διάφορα συστήματα λογισμικού που διαφέρουν ως προς τα χαρακτηριστικά μεγέθους και πολυπλοκότητας και αντιπροσωπεύουν συστήματα λογισμικού που χρησιμοποιούνται στην πράξη. Στα πλαίσια της αξιολόγησης της χρησιμότητας και της εφαρμοσιμότητας στην πράξη της προτεινόμενης μεθοδολογίας, για καθένα από τα υπό εξέταση συστήματα λογισμικού καταγράφηκαν τόσο οι περιπτώσεις πεδίων που ανιχνεύονται ως κατάλληλες για αυτοματοποιημένη εφαρμογή της αναδόμησης, όσο και τα suggested refactorable πεδία. Όσον αφορά την αξιολόγηση της κλιμακωσιμότητας της προτεινόμενης μεθοδολογίας, κατεγράφησαν για καθένα σύστημα λογισμικού οι χρόνοι εκτέλεσης της διαδικασίας ανίχνευσης των προτάσεων αναδόμησης. Τα αποτελέσματα των προαναφερθέντων πειραμάτων παρουσιάζονται και χρησιμοποιούνται προκειμένου να εξαχθούν ορισμένα χρήσιμα συμπεράσματα. Τέλος, η παρούσα διπλωματική εργασία καταγράφει τους περιορισμούς και τις ελλείψεις που παρουσιάζει η προτεινόμενη προσέγγιση αναδόμησης προς το πρότυπο Null Object. Οι περιορισμοί αυτοί μπορούν να γίνουν αντικείμενο μελλοντικής ερευνητικής μελέτης, ώστε να επεκταθεί και εμπλουτιστεί η προτεινόμενη μεθοδολογία. The need to ensure the longevity and competitiveness of modern software systems has led to the adoption of the evolutionary software development methodology, according to which the software evolves throughout its life cycle, even past its release. However, the continuous modifications to which a software system is subject, can lead to a gradual deterioration of its design quality. The methodology of refactoring to patterns, which is one of the key principles of evolutionary design, aims towards improving the design quality of software. Refactoring is the process of applying small and formalized transformations to the internal structure of the software, in order to improve some of its quality characteristics, without changing its externally observable behavior. Design patterns, on the other hand, are widely accepted, ready or almost ready high-level design solutions to commonly occurring design problems. The technique of refactoring to patterns attempts to combine the benefits of refactoring with the advantages of design patterns, with the ultimate aim of improving the design quality of a software system. However, refactoring is a highly demanding process, both in terms of effort required, and of time that should be spent in order to be performed safely, without introducing errors and by guaranteeing the preservation of the software’s initial behavior. The above requirements combined with the constant growth of the size of modern software systems make manual refactoring difficult to be done by software engineers. The value of automation the process of refactoring has been confirmed by the software industry and a plethora of automatic refactoring tools has been developed. However, the majority of automatic refactoring tools support only primitive refactorings, without enabling the automated execution of more complex refactorings, such as refactorings aimed at introducing a design pattern. This thesis intends to contribute a solution to the above problem, by examining the problem of automating the refactoring to Null Object design pattern. The Null Object pattern, based on the principles of inheritance and polymorphism, should be used in cases where repetitive checks if an object is not null before sending a message to it exist throughout the code. The aim of the developed methodology is the automatic identification of cases where it is possible to apply the Null Object design pattern. Moreover, the proposed approach allows, for cases that meet the criteria for automatic implementation of the refactoring, the automatic reconstruction of the source code in order for the structure of the pattern to be implemented. More specifically, the proposed methodology is limited to the detection and removal of conditional logic that checks whether a field is equal or not to null before invocating some of its methods, in order to avoid causing a Null Pointer Exception, since developer is not sure whether the field has been assigned value other than null. In order to define the problem of identification of refactoring to Null Object opportunities, the proposed identification methodology, first, tries to identify in each class of the examined code those of its fields which are of type of some class that belongs to the system under consideration, in order to be possible to apply the refactoring process. These fields are then examined in order to determine whether they meet a set of selected criteria which denote that there is a high probability to exist in the class they are defined conditional expressions that check whether their value equals null or not. Each field that meets the criteria of the previous analysis is characterized as candidate for the application of refactoring to Null Object pattern. It is then examined whether there exist conditional expressions that check whether the field is equal or not to null and which meet a set of criteria which allow their removal, while ensuring that no errors are introduced and maintaining the software behavior. Only the fields for which conditional statements candidates for elimination will be detected, will be finally considered suitable for the application of refactoring to Null Object pattern, since only then will we benefit from the use of the pattern. Moreover, a third set of criteria is examined in order to determine whether for the candidate fields the application of the refactoring to the Null Object pattern can be automated. Otherwise, the proposed methodology will classify this field as suggested refactorable, since it requires the intervention of the programmer in order for the refactoring to Null Object pattern to be applied. Regarding the automatic identification of refactoring to Null Object candidates, the proposed methodology is based on the technique of static analysis of the examined source code in order for its Abstract Syntax Tree (AST) to be produced. The AST tree is analyzed so as to detect the fields and conditional statements that satisfy the preconditions defined by the methodology, while for a specific subset of the identification criteria that the required information could not be drawn from it, the Control Flow Graph (CFG) and the Program Dependence Graph (PDG) were used. The refactoring suggestions that arise as a result of the identification process and are presented to the user, correspond to conditional statements that their branch condition checks the value of a candidate for refactoring field. These suggestions are presented to the user sorted according to whether they can be eliminated, and grouped per candidate field. Then, the user is able to preview the refactoring suggestions one by one and select the ones who wishes to apply. During the application of a user-selected refactoring suggestion, the abstract syntax tree of the examined code is being restructured and the user is given the option to preview the proposed refactoring prior to selecting its application, as well as the option to reject it. When the user confirms the application of the proposed refactoring, the transformations of the AST tree are used in order to modify the source code of the software without user’s contribution. During the application of a refactoring to Null Object pattern, the transformations applied to the AST tree intend to apply the structural elements of the pattern in the reconstructed system, as well as to guarantee the preservation of the initial behavior of the system under consideration. The structural elements that make up the Null Object pattern, when following the approach of abstract superclass, is the client class that defines the candidate field, the field for which conditional statements are eliminated, the abstract class and its concrete subclasses. Consequently, the transformations performed during refactoring are summarized in the creation of the abstract class and its concrete Null Object subclass whose methods will have the suitable behavior in order to be able to eliminate as many conditional statements from the program. In addition, the selected field should be declared having as type the abstract superclass and instantiated with an object of the Null Object subclass. Finally, the client class should be appropriately modified, in order for the conditional statements to be eliminated and also for the software behavior to be maintained the same. The proposed methodology has been implemented with the use of Java programming language and also of the JDT and LTK Eclipse libraries and has been integrated in the already existing refactoring tool for Eclipse IDE, JDeodorant, as part of it. The tool JDeodorant, on which the implementation of the proposed methodology was based, is an Eclipse plug-in that allows the automatic application of refactorings which solve the design problems «God Class», «Long Method», «Type Checking» and «Feature Envy». After having constructed the corresponding support tool, the proposed methodology was tested on several open source software systems in order to evaluate its effectiveness both in terms of its usefulness and applicability as well as of its scalability. Particular attention was given to use a large number of software systems in the experimental evaluation that were big in terms of size and complexity. This decision was taken for the sake of completeness, so that the usefulness and scalability of the methodology be examined in several software systems that differ in size and complexity and represent software systems used in practice. In the context of evaluating the usefulness and applicability of the proposed methodology, both cases of fields detected as suitable for automated application of refactoring, and cases of the suggested refactorable fields are recorded for each of the examined software systems. Regarding the evaluation of the scalability of the proposed methodology, the execution time required for the identification process was recorded for each of the examined software systems. The results of the above experiments are being presented and used to infer some useful conclusions. Finally, the present thesis records the limitations and the deficiencies of the proposed methodology of refactoring to Null Object pattern. These limitations can be the subject of future research study to extend and enrich the proposed methodology.
|
---|