Science Wiki
Advertisement

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

[1]



Στην Πληροφορική ως αντικειμενοστρεφής προγραμματισμός (object-oriented programming), ορίζεται ένα "προγραμματιστικό υπόδειγμα" το οποίο εμφανίστηκε στα τέλη της δεκαετίας του 1960 και καθιερώθηκε κατά τη δεκαετία του 1990, αντικαθιστώντας σε μεγάλο βαθμό το παραδοσιακό υπόδειγμα του δομημένου προγραμματισμού.


Ετυμολογία[]

Η ονομασία "Αντικειμενοστρεφής " σχετίζεται ετυμολογικά με την λέξη "αντικείμενο".


Εισαγωγή[]

Στον ΑΠ ο χειρισμός σχετιζόμενων δεδομένων και των διαδικασιών που επενεργούν σε αυτά γίνεται από κοινού, μέσω μίας δομής δεδομένων που τα περιβάλλει ως αυτόνομη οντότητα με ταυτότητα και δικά της χαρακτηριστικά.

Αυτή η δομή δεδομένων καλείται "αντικείμενο" και αποτελεί στιγμιότυπο ενός σύνθετου, και πιθανώς οριζόμενου από το χρήστη, τύπου δεδομένων ονόματι "κλάση" ο οποίος προδιαγράφει τόσο τα δεδομένα όσο και τις σχετικές διαδικασίες.

Οι αιτίες που ώθησαν στην ανάπτυξη του ΑΠ ήταν οι ίδιες με αυτές που οδήγησαν στην ανάπτυξη του δομημένου προγραμματισμού (ευκολία συντήρησης, οργάνωσης, χειρισμού και επαναχρησιμοποίησης κώδικα μεγάλων και πολύπλοκων εφαρμογών), όμως τελικώς η αντικειμενοστρέφεια επικράτησε καθώς μπορούσε να αντεπεξέλθει σε προγράμματα πολύ μεγαλύτερου όγκου και πολυπλοκότητας.

Ιστορικό[]

Οι περισσότερες αντικειμενοστρεφείς έννοιες εμφανίστηκαν αρχικά στη Γλώσσα Προγραμματισμού "Simula 67", η οποία ήταν προσανατολισμένη στην εκτέλεση προσομοιώσεων του πραγματικού κόσμου.

Οι ιδέες της Simula 67 επηρέασαν κατά τη δεκαετία του '70 την ανάπτυξη της "Smalltalk", της γλώσσας που εισήγαγε τον όρο αντικειμενοστρεφής προγραμματισμός. 

Η Smalltalk αναπτύχθηκε από τον Άλαν Κέι της εταιρείας Xerox στο πλαίσιο μίας εργασίας με στόχο τη δημιουργία ενός χρήσιμου, αλλά και εύχρηστου, προσωπικού υπολογιστή. Όταν η τελική έκδοση της Smalltalk έγινε διαθέσιμη το 1980 η έρευνα για την αντικατάσταση του δομημένου προγραμματισμού με ένα πιο σύγχρονο υπόδειγμα ήταν ήδη εν εξελίξει.

Στη γλώσσα αυτή όλοι οι τύποι δεδομένων ήταν κλάσεις (δεν υπήρχαν δηλαδή πιο παραδοσιακές δομές δεδομένων παρά μόνο αντικείμενα).

Την ίδια περίπου εποχή, και επίσης με επιρροές από τη Simula, ολοκληρωνόταν η ανάπτυξη της Γλώσσας C++ ως μίας ισχυρής επέκτασης της δημοφιλούς γλώσσας προγραμματισμού Γλώσσας C στην οποία είχαν "μεταμοσχευθεί" αντικειμενοστρεφή χαρακτηριστικά. Η επιρροή της C++ καθ' όλη της δεκαετία του '80 ήταν καταλυτική με αποτέλεσμα τη σταδιακή κυκλοφορία αντικειμενοστρεφών εκδόσεων πολλών γνωστών διαδικαστικών γλωσσών προγραμματισμού. Κατά το πρώτο ήμισυ της δεκαετίας του '90 η βαθμιαία καθιέρωση στους μικροϋπολογιστές των γραφικών διασυνδέσεων χρήστη (GUI), για την ανάπτυξη των οποίων ο ΑΠ φαινόταν ιδιαιτέρως κατάλληλος, και η επίδραση της C++ οδήγησαν στην επικράτηση της αντικειμενοστρέφειας ως βασικού προγραμματιστικού υποδείγματος.

Το 1995 η εμφάνιση της Γλώσσας Java, μίας ιδιαίτερα επιτυχημένης, πλήρως αντικειμενοστρεφούς γλώσσας που ομοίαζε συντακτικώς με τη C/C++ και προσέφερε πρωτοποριακές για την εποχή δυνατότητες, έδωσε νέα ώθηση στον ΑΠ. Παράλληλα εμφανίστηκαν ποικίλες άτυπες βελτιώσεις στο βασικό προγραμματιστικό υπόδειγμα, όπως

  • οι αντικειμενοστρεφείς "γλώσσες μοντελοποίησης λογισμικού",
  • τα σχεδιαστικά πρότυπα κλπ.

Το 2001 η Microsoft εστίασε την προσοχή της στην πλατφόρμα .NET, μία ανταγωνιστική της Java πλατφόρμα ανάπτυξης και εκτέλεσης λογισμικού η οποία ήταν εξ' ολοκλήρου προσανατολισμένη στην αντικειμενοστρέφεια.

Έννοιες[]

Κεντρική ιδέα στον αντικειμενοστρεφή προγραμματισμό είναι η κλάση (class), μία αυτοτελής και αφαιρετική αναπαράσταση κάποιας κατηγορίας οντοτήτων (πιθανώς του πραγματικού κόσμου) σε ένα περιβάλλον προγραμματισμού.

Πρακτικώς αυτή είναι ένας Τύπος Δεδομένων, ή αλλιώς το προσχέδιο μίας δομής δεδομένων με δικά της περιεχόμενα, τόσο μεταβλητές όσο και διαδικασίες.

Τα περιεχόμενα αυτά δηλώνονται είτε ως δημόσια (public) είτε ως ιδιωτικά (private), με τα ιδιωτικά να μην είναι προσπελάσιμα από κώδικα εκτός της κλάσης. Οι διαδικασίες των κλάσεων συνήθως καλούνται μέθοδοι (methods) και οι μεταβλητές τους γνωρίσματα (attributes) ή πεδία (fields).

Αντικείμενο (object) είναι το στιγμιότυπο μίας κλάσης, δηλαδή αυτή καθαυτή η δομή δεδομένων (με αποκλειστικά δεσμευμένο χώρο στη μνήμη) βασισμένη στο «καλούπι» που προσφέρει η κλάση. Παραδείγματος χάριν, σε μία αντικειμενοστρεφή γλώσσα προγραμματισμού θα μπορούσαμε να ορίσουμε κάποια κλάση ονόματι BankAccount, η οποία αναπαριστά έναν τραπεζικό λογαριασμό, και να δηλώσουμε ένα αντικείμενο της με όνομα MyAccount. Το αντικείμενο αυτό θα έχει δεσμεύσει χώρο στη μνήμη με βάση τις μεταβλητές και τις μεθόδους που περιγράψαμε όταν δηλώσαμε την κλάση. Έτσι, στο αντικείμενο θα μπορούσε να περιέχεται ένα γνώρισμα Balance (=υπόλοιπο) και μία μέθοδος GetBalance (=επέστρεψε το υπόλοιπο). Ας σημειωθεί εδώ πως τα αντικείμενα μίας κλάσης μπορούν να προσπελάσουν τις ιδιωτικές ιδιότητες άλλων αντικειμένων της ίδιας κλάσης.

Ενθυλάκωση Δεδομένων (data encapsulation) καλείται η ιδιότητα που προσφέρουν οι κλάσεις να «κρύβουν» τα ιδιωτικά δεδομένα τους από το υπόλοιπο πρόγραμμα και να εξασφαλίζουν πως μόνο μέσω των δημόσιων μεθόδων τους θα μπορούν αυτά να προσπελασθούν.

Αφαίρεση Δεδομένων καλείται η ιδιότητα των κλάσεων να αναπαριστούν αφαιρετικά πολύπλοκες οντότητες στο προγραμματιστικό περιβάλλον. Επίσης οι κλάσεις προσφέρουν και αφαίρεση ως προς τον υπολογιστή, εφόσον η καθεμία μπορεί να θεωρηθεί ένας μικρός και αυτάρκης υπολογιστής (με δική του κατάσταση, μεθόδους και μεταβλητές).

Κληρονομικότητα ονομάζεται η ιδιότητα των κλάσεων να επεκτείνονται σε νέες κλάσεις, ρητά δηλωμένες ως κληρονόμους (υποκλάσεις ή 'θυγατρικές κλάσεις'), οι οποίες μπορούν να επαναχρησιμοποιήσουν τις μεταβιβάσιμες μεθόδους και ιδιότητες της γονικής τους κλάσης αλλά και να προσθέσουν δικές τους.

Στιγμιότυπα των θυγατρικών κλάσεων μπορούν να χρησιμοποιηθούν όπου απαιτούνται στιγμιότυπα των γονικών (εφόσον η θυγατρική είναι κατά κάποιον τρόπο μία πιο εξειδικευμένη εκδοχή της γονικής), αλλά το αντίστροφο δεν ισχύει. Παράδειγμα κληρονομικότητας είναι μία γονική κλάση Vehicle (= Όχημα) και οι δύο πιο εξειδικευμένες υποκλάσεις της Car (= Αυτοκίνητο) και Bicycle (= Ποδήλατο), οι οποίες θεωρούμε ότι "κληρονομούν" από αυτήν.

Πολλαπλή κληρονομικότητα είναι η δυνατότητα που προσφέρουν ορισμένες γλώσσες προγραμματισμού μία κλάση να κληρονομεί ταυτόχρονα από περισσότερες από μία γονικές. Από μία υποκλάση μπορούν να προκύψουν νέες υποκλάσεις που κληρονομούν από αυτήν, με αποτέλεσμα μία ιεραρχία κλάσεων που συνδέονται μεταξύ τους "ανά γενεά" με σχέσεις κληρονομικότητας.

Υπερφόρτωση μεθόδου (method overloading) είναι η κατάσταση κατά την οποία υπάρχουν, στην ίδια ή σε διαφορετικές κλάσεις, μέθοδοι με το ίδιο όνομα και πιθανώς διαφορετικά ορίσματα. Αν πρόκειται για μεθόδους της ίδιας κλάσης διαφοροποιούνται μόνο από τις διαφορές τους στα ορίσματα και στον τύπο επιστροφής.

Υποσκέλιση μεθόδου (method overriding) είναι η κατάσταση κατά την οποία μία θυγατρική κλάση και η γονική της έχουν μία μέθοδο ομώνυμη και με τα ίδια ορίσματα. Χάρις στη δυνατότητα του πολυμορφισμού ο μεταγλωττιστής «γνωρίζει» πότε να καλέσει ποια μέθοδο, βασισμένος στον τύπο του τρέχοντος αντικειμένου. Δηλαδή πολυμορφισμός είναι η δυνατότητα των αντικειμενοστρεφών μεταγλωττιστών να αποφασίζουν δυναμικά ποια είναι η κατάλληλη να κληθεί μέθοδος σε συνθήκες υποσκέλισης.

Αφηρημένη κλάση (abstract class) είναι μία κλάση που ορίζεται μόνο για να κληρονομηθεί σε θυγατρικές υποκλάσεις και δεν υπάρχουν δικά της στιγμιότυπα (αντικείμενα). Η αφηρημένη κλάση ορίζει απλώς ένα "συμβόλαιο" το οποίο θα πρέπει να ακολουθούν οι υποκλάσεις της όσον αφορά τις υπογραφές των μεθόδων τους (όπου ως υπογραφή ορίζεται το όνομα, τα ορίσματα και η τιμή επιστροφής μίας διαδικασίας).

Μία αφηρημένη κλάση μπορεί να έχει και μη αφηρημένες μεθόδους οι οποίες υλοποιούνται στην ίδια την κλάση (αν και φυσικά μπορούν να υποσκελίζονται σε υποκλάσεις). Αντιθέτως οι αφηρημένες μέθοδοι μίας αφηρημένης κλάσης είναι απλώς ένας ορισμός της υπογραφής τους και εναπόκειται στις υποκλάσεις να τις υλοποιήσουν.

Μία αφηρημένη κλάση που δεν έχει γνωρίσματα και όλες οι μέθοδοι της είναι αφηρημένες και δημόσιες καλείται διασύνδεση (interface). Οι κλάσεις που κληρονομούν από μία διασύνδεση λέγεται ότι την "υλοποιούν".

Ακολουθεί ένα απλό παράδειγμα σε γλώσσα προγραμματισμού Java:

interface Logger
{
   public void log(String msg);
}

class ConsoleLogger implements Logger
{
   public void log(String msg)
   {
      System.err.println("\nConsole logging..." + msg + "\n");
   }
}

class FileLogger implements Logger
{
   public void log(String msg)
   {
       System.out.println("\nFile logging..." + msg + "\n");
   }
}

public class LogTest
{
    public static void main(String[] args)
    {
       if(args.length != 1)
       {
           System.out.println("\nError. Exiting...");
           return;
       }
       Logger logg;
       String choice = args[0];
       if(choice.equals("FileLogger"))
          logg = new FileLogger();
       else if(choice.equals("ConsoleLogger"))
          logg = new ConsoleLogger();
       else
       {
          System.err.println("\nError. Exiting...");
          return;
       }
       logg.log("Log This!");
    }
}

Στο παραπάνω παράδειγμα ορίζουμε μία διασύνδεση Logger η οποία παρέχει την υπογραφή μίας μεθόδου log, που υποθέτουμε πως πρέπει να καταγράφει κάπου πληροφορίες για τα σφάλματα που συναντά η εφαρμογή όταν εκτελείται (οι πληροφορίες αυτές της μεταβιβάζονται με το αλφαριθμητικό όρισμα msg). Η κλάση ConsoleLogger και η κλάση FileLogger είναι δύο διαφορετικές κλάσεις που υλοποιούν τη διασύνδεση Logger και υποσκελίζουν, η καθεμία με διαφορετικό τρόπο, τη μέθοδο log ώστε η μία να καταγράφει πληροφορίες στην οθόνη και η άλλη σε κάποιο αρχείο.

Το πρόγραμμα LogTest είναι ένα μικρό δοκιμαστικό πρόγραμμα το οποίο δέχεται ως όρισμα γραμμής εντολών το πού επιθυμεί ο χρήστης να γίνεται η καταγραφή και δημιουργεί ένα στιγμιότυπο της αντίστοιχης κλάσης: της ConsoleLogger ή της FileLogger. Το στιγμιότυπο αυτό δηλώνεται με το γενικότερο τύπο Logger, τον τύπο δηλαδή της διασύνδεσης που υλοποιούν και οι δύο κλάσεις, αλλά χάρη στον πολυμορφισμό καλείται αυτομάτως η κατάλληλη εκδοχή της μεθόδου log.

Αρχές αντικειμενοστρεφούς σχεδίασης[]

Με την πάροδο του χρόνου κωδικοποιήθηκαν κάποιες ανεπίσημες αρχές για την ορθή σχεδίαση αντικειμενοστρεφών συστημάτων λογισμικού. Οι αρχές αυτές παρουσιάστηκαν κατά καιρούς σε βιβλία και άρθρα ακαδημαϊκών και αναγνωρισμένων μηχανικών λογισμικού. Οι σπουδαιότερες αρχές είναι οι παρακάτω:

  • Αρχή ανοικτότητας - κλειστότητας (open-closed principle), του δημιουργού της γλώσσας προγραμματισμού Eiffel Μπέρτραντ Μέιερ. Η αρχή αυτή δηλώνει πως τα συστατικά ενός προγράμματος πρέπει να είναι "ανοικτά" ως προς την επέκταση των δυνατοτήτων του συστήματος αλλά "κλειστά" ως προς αλλαγές στην υλοποίηση του. Πρακτικώς αυτό σημαίνει οι διάφορες κλάσεις και τα υπόλοιπα τμήματα λογισμικού να μη χρειάζεται να τροποποιηθούν σε περίπτωση που προστεθεί νέα λειτουργικότητα στο σύστημα (π.χ. μία νέα κλάση) προκειμένου να αξιοποιήσουν αυτή τη λειτουργικότητα. Βεβαίως είναι αδύνατο να μη χρειάζεται να τροποποιηθεί τίποτα, οπότε αυτό που επιτάσσει στην πραγματικότητα η εν λόγω αρχή είναι η ελαχιστοποίηση και η συγκέντρωση, σε ένα μικρό τμήμα του κώδικα κατά προτίμηση, των γραμμών που θα πρέπει να αλλάξουν. Αυτό συνήθως επιτυγχάνεται μέσω αφαίρεσης (με αφηρημένες κλάσεις ή διασυνδέσεις και πραγματικές κλάσεις που κληρονομούν από αυτές) και με χρήση του πολυμορφισμού. Έτσι, στο παράδειγμα της προηγούμενης ενότητας αν προσθέσουμε και μία τρίτη υλοποίηση της διασύνδεσης Logger, την PrinterLogger η οποία "καταγράφει" σφάλματα αποστέλλοντας τα για εκτύπωση, o κώδικας του προγράμματος γίνεται:
public class LogTest
{
    public static void main(String[] args)
    {
       if(args.length != 1)
       {
           System.out.println("\nError. Exiting...");
           return;
       }
       Logger logg;
       String choice = args[0];
       if(choice.equals("FileLogger"))
          logg = new FileLogger();
       else if(choice.equals("ConsoleLogger"))
          logg = new ConsoleLogger();
       else if(choice.equals("PrinterLogger"))
          logg = new PrinterLogger();
       else
       {
          System.err.println("\nError. Exiting...");
          return;
       }
       logg.log("Log This!");
    }
}

Όπως φαίνεται μόνη αλλαγή είναι η προσθήκη μίας ακόμα δήλωσης else if. Η εντολή

logg.log("Log This!");

μπορεί να λειτουργήσει και με αντικείμενα του νέου τύπου χωρίς καμία τροποποίηση. Μία συνηθισμένη τακτική για διασφάλιση της κλειστότητας του ολικού προγράμματος ως προς την υλοποίηση μίας κλάσης, είναι η συνειδητή προσπάθεια για δήλωση όλων των γνωρισμάτων της ως ιδιωτικών. Έτσι η προσπέλαση των πεδίων της κλάσης μπορεί να ελεγχθεί εξ ολοκλήρου μέσω ειδικών δημόσιων μεθόδων της, γεγονός που διευκολύνει κατά πολύ την αποσφαλμάτωση: στις μεθόδους αυτές συνήθως συγκεντρώνονται οι έλεγχοι επιτρεπτών τιμών για τα πεδία, έλεγχοι κατάλληλων συνθηκών κλπ.

  • Αρχή υποκατάστασης Λίσκοφ (Liskov substitution principle), της επιστήμονα υπολογιστών Μπάρμπαρα Λίσκοφ. Η αρχή αυτή συμπυκνώνεται στον παρακάτω κανόνα για σχηματισμό μίας ορθής ιεραρχίας κλάσεων: μία κλάση Κ1 μπορεί να υλοποιηθεί ως υποκλάση μίας κλάσης Κ2 αν κάθε πρόγραμμα Π το οποίο λειτουργεί με αντικείμενα Κ2 συμπεριφέρεται με τον ίδιο τρόπο και με αντίστοιχα αντικείμενα Κ1. Έτσι με την αρχή υποκατάστασης Λίσκοφ φαίνεται πως για να οριστεί μία κλάση ως θυγατρική μίας άλλης δεν αρκεί να έχουν διαισθητικά μία ανάλογη εννοιολογική σχέση (π.χ. μία κλάση που αναπαριστά όχημα και μία που αναπαριστά αυτοκίνητο) αλλά, στο πλαίσιο του υπό εξέταση προγράμματος, τα αντικείμενα της υποκλάσης να έχουν πάντα την ίδια προγραμματιστική συμπεριφορά με τα αντικείμενα της υπερκλάσης υπό τις ίδιες συνθήκες.
  • Αρχή αντιστροφής εξαρτήσεων (dependency inversion principle), του μηχανικού λογισμικού Ρόμπερτ Σέσιλ Μάρτιν. Η αρχή αυτή πρακτικά αποτελεί εκλέπτυνση της αρχής ανοικτότητας - κλειστότητας, προϋποθέτοντας όμως χρήση και της αρχής υποκατάστασης Λίσκοφ. Αφορά ιεραρχίες κληρονομικότητας κλάσεων και τη χρήση αντικειμένων αυτών των ιεραρχιών από εξωτερικά προγράμματα. Στα πλαίσια της αρχής αντιστροφής εξαρτήσεων ένα τμήμα λογισμικού Α (π.χ. μία κλάση) το οποίο χρησιμοποιεί τις υπηρεσίες που παρέχει ένα άλλο τμήμα λογισμικού Β, καλώντας για παράδειγμα μία μέθοδο του, θεωρείται στοιχείο "υψηλότερου επιπέδου" σε σχέση με το Β. Η αρχή λέει πως τα υψηλού επιπέδου στοιχεία δεν πρέπει να εξαρτώνται από την υλοποίηση χαμηλότερου επιπέδου στοιχείων, αλλά πως και τα δύο πρέπει να βασίζονται σε ενδιάμεσα επίπεδα αφαίρεσης. Στην πράξη αυτή η αφαίρεση είναι μία διασύνδεση (ή αφηρημένη κλάση) την οποία γνωρίζει το υψηλού επιπέδου στοιχείο Α και υλοποιεί το χαμηλού επιπέδου στοιχείο Β. Ακόμα και αν το Β αλλαχθεί με μία κλάση Γ η οποία επίσης υλοποιεί την ίδια διασύνδεση, το Α θα πρέπει να συνεχίσει να λειτουργεί χωρίς καμία τροποποίηση. Η αρχή αντιστροφής εξαρτήσεων δεν είναι παρά ένα απτό παράδειγμα χρήσης ιεραρχικών επιπέδων με τη βοήθεια ενδιάμεσων αφαιρέσεων, μίας τεχνικής που εφαρμόζεται κατά κόρον στην επιστήμη υπολογιστών (για ένα άλλο παράδειγμα βλέπε δίκτυα υπολογιστών).
  • Αρχή διαχωρισμού διασυνδέσεων (interface segregation principle), του μηχανικού λογισμικού Ρόμπερτ Σέσιλ Μάρτιν. Η εν λόγω αρχή σημαίνει ότι σε περιπτώσεις όπου διαφορετικά υποσύνολα μεθόδων μίας κλάσης αφορούν διαφορετικές περιπτώσεις χρήσης της κλάσης, σκόπιμο είναι να ορίζουμε επιμέρους διασυνδέσεις τις οποίες η κλάση θα υλοποιεί. Κάθε τέτοια διασύνδεση θα ορίζει μόνο το αντίστοιχο υποσύνολο των μεθόδων.
  • Αρχή μοναδικής αρμοδιότητας (single responsibility principle), των Τομ Ντε Μάρκο και Μέιρ Πέιτζ Τζόουνς. Σύμφωνα με την αρχή αυτή κάθε κλάση θα πρέπει να έχει μόνο μία, καλά ορισμένη και διαχωρισμένη από το υπόλοιπο πρόγραμμα αρμοδιότητα, η ύπαρξη της οποίας να εξυπηρετεί ένα συγκεκριμένο σκοπό. Αν μπορούμε να εντοπίσουμε σε μία κλάση Α δύο διαφορετικές αρμοδιότητες, τότε η καλύτερη λύση είναι η διάσπαση της σε δύο κλάσεις Β' και Γ', καθεμία από τις οποίες θα λάβει ένα υποσύνολο των πεδίων και των μεθόδων της Α. Τα υποσύνολα αυτά θα είναι ξένα μεταξύ τους, οπότε με το αντίστροφο σκεπτικό αν μπορούμε να διασπάσουμε μία κλάση Α σε δύο άλλες κλάσεις (π.χ. σε περίπτωση που κάποιες μέθοδοι δε χρησιμοποιούν κάποια γνωρίσματα, οπότε οι μεν μπορούν να καταλήξουν στη μία κλάση Β' και τα πεδία στην άλλη κλάση Γ') τότε πιθανώς η κλάση να παραβιάζει την αρχή μοναδικής αρμοδιότητας. Έτσι έχουν προταθεί κάποιες μετρικές οι οποίες επιχειρούν να προσδιορίσουν την έλλειψη συνοχής (cohesion) σε μία κλάση, δηλαδή το κατά πόσον οι μέθοδοι της δε σχετίζονται με τα γνωρίσματα της. Συνήθως η συνοχή αντιπαραβάλλεται με τη σύζευξη (coupling), δηλαδή το βαθμό στον οποίον μία κλάση εξαρτάται από κάποιες άλλες, και τα δύο αυτά μεγέθη είναι αντιστρόφως ανάλογα. Οι πιο συνηθισμένες μετρικές έλλειψης συνοχής είναι οι ακόλουθες:
    • 1) LCOM1 = P - Q αν P > Q, διαφορετικά LCOM1 = 0. Μία τιμή LCOM1 = 0 υποδεικνύει συνεκτική κλάση, ενώ αν LCOM1 > 0 η κλάση καλό είναι να διασπαστεί. Η μετρική LCOM1 παρουσιάζει κάποια προβλήματα, όπως π.χ. ότι δίνει τιμή 0 για κλάσεις πολύ διαφορετικές μεταξύ τους. Τα P, Q υπολογίζονται με τον ακόλουθο αλγόριθμο (σε ψευδοκώδικα):
  P = 0; Q = 0;
  Για κάθε ζεύγος μεθόδων της κλάσης
  do
  {
     Αν τα σύνολα των πεδίων που χρησιμοποιούν οι δύο τρέχουσες μέθοδοι είναι ξένα μεταξύ τους
        P = P + 1;
     Διαφορετικά
        Q = Q + 1;
  }
    • 2) LCOM2 = 1 - sum(mA)/(m*a), όπου m το πλήθος των μεθόδων της κλάσης, a το πλήθος των πεδίων της, mA το πλήθος των μεθόδων που προσπελαύνουν ένα γνώρισμα και sum(mA) το άθροισμα των mA για όλα τα πεδία μίας κλάσης. Η μετρική LCOM2 αποτελεί το μέσο όρο των ποσοστών των μεθόδων που δε χρησιμοποιούν κάθε γνώρισμα. LCOM2 = 0 (υψηλή συνοχή) σημαίνει πως όλες οι μέθοδοι της κλάσης χρησιμοποιούν όλα τα πεδία της, ενώ LCOM2 = 1 (καμία συνοχή) σημαίνει πως καμία μέθοδος δεν προσπελαύνει κανένα πεδίο.
    • 3) LCOM3 = (m - sum(mA)/a) / (m-1). Η μετρική LCOM3 λαμβάνει τιμές από 0 (υψηλή συνοχή) έως 2 (καμία συνοχή). Τιμές μεγαλύτερες του 1 σημαίνουν πως με βεβαιότητα υπάρχει τουλάχιστον ένα "νεκρό γνώρισμα", δηλαδή γνώρισμα το οποίο δεν προσπελαύνεται από καμία μέθοδο της κλάσης.

UML[]

Μετά την ευρεία διάδοση του ΑΠ κατά τη δεκαετία του '90, το αντικειμενοστρεφές μοντέλο σχεδίασης (με κλάσεις, κληρονομικότητα, αντικείμενα και τυποποιημένες αλληλεπιδράσεις μεταξύ τους) επικράτησε ακόμη και για μοντελοποίηση που δεν περιελάμβανε προγραμματισμό (π. χ. σχήματα βάσεων δεδομένων). Έτσι αναπτύχθηκαν διάφορες πρότυπες γλώσσες μοντελοποίησης λογισμικού οι οποίες τυποποιούσαν οπτικά σύμβολα και συμπεριφορές με στόχο την αφαιρετική περιγραφή της λειτουργίας και της δομής ενός υπολογιστικού συστήματος. Οι γλώσσες αυτές είχαν εξ' αρχής έναν εμφανή αντικειμενοστρεφή προσανατολισμό. Τελικά οι πιο δημοφιλείς από αυτές ενοποιήθηκαν στο κοινό πρότυπο UML που η πρώτη του έκδοση οριστικοποιήθηκε το 1997.

Η UML πλέον είναι η πρότυπη γλώσσα μοντελοποίησης στη μηχανική λογισμικού. Χρησιμοποιείται για τη γραφική απεικόνιση, προσδιορισμό, κατασκευή και τεκμηρίωση των στοιχείων ενός συστήματος λογισμικού. Μπορεί να χρησιμοποιηθεί σε διάφορες φάσεις ανάπτυξης, από την ανάλυση απαιτήσεων ως τον έλεγχο ενός ολοκληρωμένου συστήματος.

Αποτελείται από ένα σύνολο προσυμφωνημένων όρων, συμβόλων και διαγραμμάτων που επιτρέπουν:

  • την εμφάνιση των ορίων ενός συστήματος και των βασικών λειτουργιών του, χρησιμοποιώντας «περιπτώσεις χρήσης» (use-cases) και «actors».
  • την επεξήγηση της πραγματοποίησης των περιπτώσεων χρήσης με «διαγράμματα αλληλεπίδρασης».
  • την αναπαράσταση μιας στατικής δομής ενός συστήματος χρησιμοποιώντας «διαγράμματα κλάσεων».
  • τη μοντελοποίηση της συμπεριφοράς των αντικειμένων με «διαγράμματα καταστάσεων».
  • την αποκάλυψη της υλοποίησης της αρχιτεκτονικής με «διαγράμματα συστατικών» και «ανάπτυξης».
  • την επέκταση της λειτουργικότητας με «στερεότυπα».

Τα διαγράμματα κλάσεων της UML ορίζουν γεωμετρικά σχήματα ως συμβολισμούς για τα αντικείμενα, τις κλάσεις και τις διασυνδέσεις, ενώ διαφόρων τύπων γραμμές χρησιμοποιούνται για να συνδέουν αυτά τα σχήματα και να υποδεικνύουν έτσι τον τρόπο που κληρονομούν, συνεργάζονται ή εξαρτώνται μεταξύ τους.

Τα αντικείμενα της ίδιας κλάσης αναπαριστώνται με ένα μόνο Γεωμετρικό Σχήμα. Όταν ένα αντικείμενο χρησιμοποιεί κώδικα κάποιας άλλης κλάσης (π.χ. καλώντας μία μέθοδο της), σύμφωνα με το πρότυπο της UML υπάρχει μία "εξάρτηση" (dependency) μεταξύ τους η οποία αναπαρίσταται με μία διακεκομμένη γραμμή. Αυτή η εξάρτηση μπορεί να είναι "συσχέτιση" (association), ένας τύπος εξάρτησης που υπονοεί πραγματική συνύπαρξη στη μνήμη στιγμιοτύπων των συμμετεχόντων κλάσεων κατά το "χρόνο εκτέλεσης", "συνάθροιση" (aggregation), ένας τύπος συσχέτισης ο οποίος σημαίνει ότι το ένα αντικείμενο μπορεί να περιέχει στιγμιότυπα της άλλης κλάσης ως γνωρίσματα του, ή "σύνθεση" (composition), ένας πιο ισχυρός τύπος συνάθροισης που υπονοεί πως ο χρόνος ζωής των αντικειμένων είναι κοινός (δημιουργούνται και καταστρέφονται στη μνήμη ταυτόχρονα). Καθεμία από αυτές τις σχέσεις συμβολίζεται οπτικά με ένα διαφορετικό τύπο γραμμής μεταξύ των συμμετεχόντων κλάσεων, ενώ μπορεί να υπάρχουν και εξαρτήσεις οι οποίες δεν είναι καν συσχετίσεις.

[[Σχεδιαστικό Πρότυπο|Σχεδιαστικά πρότυπα

Κατά τα τέλη της δεκαετίας του '70 ένας αρχιτέκτονας ονόματι Κρίστοφερ Αλεξάντερ επιχείρησε να βρει και να καταγράψει αποδεδειγμένα ποιοτικούς σχεδιασμούς στον τομέα των κατασκευών. Έτσι μελέτησε πολλές διαφορετικές κατασκευές που εξυπηρετούσαν τον ίδιο σκοπό και προσπάθησε να ανακαλύψει κοινά στοιχεία, τα οποία κατηγοριοποίησε σε σχεδιαστικά πρότυπα (design patterns). Το 1987 η ιδέα της εύρεσης σχεδιαστικών προτύπων εφαρμόστηκε για πρώτη φορά στη μηχανική λογισμικού και μέχρι τα μέσα της δεκαετίας του '90 η εν λόγω έννοια είχε καθιερωθεί και εξαπλωθεί, στραμμένη πλέον στον κόσμο της αντικειμενοστρέφειας.

Ένα πρότυπο σχεδίασης ορίζεται ως μία αποδεδειγμένα καλή λύση που έχει εφαρμοστεί με επιτυχία στην επίλυση ενός επαναλαμβανόμενου προβλήματος σχεδίασης συστημάτων λογισμικού. Τα πρότυπα σχεδίασης ορίζονται τόσο σε επίπεδο μακροσκοπικής σχεδίασης όσο και σε επίπεδο υλοποίησης, ενώ με τη χρήση τους ένας προγραμματιστής αντικαθιστά πρακτικώς μεγάλα τμήματα του κώδικα του με μαύρα κουτιά. Πρόκειται για αφαιρέσεις υψηλού επιπέδου που αποτελούν πλήρη υποσυστήματα, κατάλληλα ρυθμισμένα για την επίλυση συγκεκριμένων προβλημάτων και έτοιμα για χρήση. Διάφορες κατηγορίες προτύπων, για διαφορετικά προβλήματα, έχουν οριστεί και κάθε κατηγορία περιλαμβάνει πολλαπλά στοιχεία. Έτσι υπάρχουν κατασκευαστικά πρότυπα, δομικά πρότυπα, συμπεριφορικά πρότυπα κλπ.


Εσωτερική Αρθρογραφία[]

Βιβλιογραφία[]

  • Βασικές Αρχές Γλωσσών Προγραμματισμού, Ellis Horowitz, Εκδόσεις Κλειδάριθμος
  • Core Techniques and Algorithms in Game Programming, Daniel Sanchez-Crespo Dalmeau, Εκδόσεις New Riders


Ιστογραφία[]


Ikl Κίνδυνοι ΧρήσηςIkl

Αν και θα βρείτε εξακριβωμένες πληροφορίες
σε αυτήν την εγκυκλοπαίδεια
ωστόσο, παρακαλούμε να λάβετε σοβαρά υπ' όψη ότι
η "Sciencepedia" δεν μπορεί να εγγυηθεί, από καμιά άποψη,
την εγκυρότητα των πληροφοριών που περιλαμβάνει.

"Οι πληροφορίες αυτές μπορεί πρόσφατα
να έχουν αλλοιωθεί, βανδαλισθεί ή μεταβληθεί από κάποιο άτομο,
η άποψη του οποίου δεν συνάδει με το "επίπεδο γνώσης"
του ιδιαίτερου γνωστικού τομέα που σας ενδιαφέρει."

Πρέπει να λάβετε υπ' όψη ότι
όλα τα άρθρα μπορεί να είναι ακριβή, γενικώς,
και για μακρά χρονική περίοδο,
αλλά να υποστούν κάποιο βανδαλισμό ή ακατάλληλη επεξεργασία,
ελάχιστο χρονικό διάστημα, πριν τα δείτε.



Επίσης,
Οι διάφοροι "Εξωτερικοί Σύνδεσμοι (Links)"
(όχι μόνον, της Sciencepedia
αλλά και κάθε διαδικτυακού ιστότοπου (ή αλλιώς site)),
αν και άκρως απαραίτητοι,
είναι αδύνατον να ελεγχθούν
(λόγω της ρευστής φύσης του Web),
και επομένως είναι ενδεχόμενο να οδηγήσουν
σε παραπλανητικό, κακόβουλο ή άσεμνο περιεχόμενο.
Ο αναγνώστης πρέπει να είναι
εξαιρετικά προσεκτικός όταν τους χρησιμοποιεί.

- Μην κάνετε χρήση του περιεχομένου της παρούσας εγκυκλοπαίδειας
αν διαφωνείτε με όσα αναγράφονται σε αυτήν

IonnKorr-System-00-goog



>>Διαμαρτυρία προς την wikia<<

- Όχι, στις διαφημίσεις που περιέχουν απαράδεκτο περιεχόμενο (άσεμνες εικόνες, ροζ αγγελίες κλπ.)


Advertisement