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

Ποια είναι τα SOLID principles και ποιος τα ανέπτυξε;

Ο καλός πηγαίος κώδικας ξεκινά με κανόνες, προγραμματιστικά παραδείγματα και ένα κατάλληλο στυλ προγραμματισμού για αποδοτικό και καθαρό κώδικα. Αυτό ακριβώς εξασφαλίζουν οι πέντε αρχές SOLID, που διατύπωσαν οι Robert C. Martin, Bertrand Meyer και Barbara Liskov. Ακολουθώντας αυτές τις αρχές στην αντικειμενοστρεφή προγραμματισμό (OOP) με γλώσσες όπως Python ή Java, όχι μόνο γράφετε καλύτερο κώδικα, αλλά εξασφαλίζετε επίσης πιο αποτελεσματική συντήρηση κώδικα, βιώσιμο και ευέλικτο σχεδιασμό λογισμικού και μεγαλύτερη ασφάλεια μακροπρόθεσμα.

Το όνομα SOLID αντιπροσωπεύει τα σταθερά θεμέλια προγραμματισμού που πρέπει να έχει όποιος θέλει να μάθει προγραμματισμό. Το ακρωνύμιο δημιουργήθηκε από τον Michael Feathers, ο οποίος πήρε τα πρώτα γράμματα από κάθε μία από τις πέντε αρχές για να το δημιουργήσει:

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

Ποια είναι τα οφέλη των αρχών SOLID;

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

Οι αρχές SOLID δημιουργούν κώδικα:

  • Σαφές, καθαρό και ελκυστικό: Το λογισμικό και οι κώδικες είναι πιο κατανοητά, πιο αποτελεσματικά και απλά φαίνονται καλύτερα.
  • Εύκολο στη συντήρηση: Η απλή και σαφής δομή διευκολύνει τη συντήρηση και τη διαχείριση τόσο του νέου κώδικα όσο και του παλαιού κώδικα από πολλούς συνεργάτες.
  • Προσαρμόσιμο, επεκτάσιμο, επαναχρησιμοποιήσιμο: Χάρη στη βελτιωμένη αναγνωσιμότητα, τη μειωμένη πολυπλοκότητα και ευθύνη, καθώς και τη μειωμένη εξάρτηση από τις κλάσεις, ο κώδικας μπορεί να επεξεργαστεί, να προσαρμοστεί και να επεκταθεί καλύτερα μέσω διεπαφών, και να επαναχρησιμοποιηθεί με ευελιξία.
  • Λιγότερο επιρρεπές σε σφάλματα: Ο καθαρός κώδικας με απλή δομή σημαίνει ότι οι αλλαγές σε ένα μέρος του κώδικα δεν επηρεάζουν κατά λάθος άλλες περιοχές ή λειτουργίες.
  • Ασφαλής και πιο αξιόπιστος: Η μείωση ή η εξάλειψη των τρωτών σημείων, των ασυμβατοτήτων και των σφαλμάτων βελτιώνει τη λειτουργικότητα και την αξιοπιστία ενός συστήματος, γεγονός που με τη σειρά του βελτιώνει την ασφάλεια.

Τι σημαίνει κάθε μία από τις αρχές SOLID;

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

SRP: Αρχή της ενιαίας ευθύνης

Ο Robert C. Martin δημιούργησε τον αρχικό ορισμό αυτής της αρχής στο έργο «Agile Software Development: Principles, Patterns and Practices» (Ευέλικτη ανάπτυξη λογισμικού: Αρχές, πρότυπα και πρακτικές), γράφοντας:

Quote

«Κάθε ενότητα λογισμικού πρέπει να έχει έναν και μόνο έναν λόγο για να αλλάξει».

Η αρχή της ενιαίας ευθύνης (SRP) ορίζει ότι κάθε κλάση στην αντικειμενοστρεφή προγραμματισμό (OOP) πρέπει να έχει μόνο μία ευθύνη. Αυτό σημαίνει ότι πρέπει να υπάρχει μόνο ένας λόγος για την τροποποίηση μιας κλάσης. Σε αντίθεση με τις συνήθεις ερμηνείες, αυτό δεν σημαίνει ότι μια κλάση ή ένα module μπορεί να έχει μόνο μία αποστολή. Αντίθετα, σημαίνει ότι πρέπει να είναι υπεύθυνη μόνο για συγκεκριμένες αποστολές που, ιδανικά, δεν αλληλεπικαλύπτονται με άλλες περιοχές.

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

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

Note

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

OCP: Αρχή ανοικτού-κλειστού

Σύμφωνα με τους Robert C. Martin και Bertrand Meyer στο έργο «Object Oriented Software Construction», το OCP ορίζει:

Quote

«Οι οντότητες λογισμικού (τάξεις, ενότητες, λειτουργίες κ.λπ.) πρέπει να είναι ανοιχτές για επέκταση, αλλά κλειστές για τροποποίηση».

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

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

LSP: Αρχή υποκατάστασης της Liskov

Σύμφωνα με τις Barbara H. Liskov και Jeannette M. Wing στο «Behavioral Subtyping Using Invariants and Constraints», το LSP ορίζει ότι:

Quote

«Ας είναι q(x) μια ιδιότητα που μπορεί να αποδειχθεί για αντικείμενα x τύπου T. Τότε, το q(y) θα πρέπει να μπορεί να αποδειχθεί για αντικείμενα y τύπου S, όπου S είναι υποτύπος του T».

Μπορεί να ακούγεται αινιγματικό, αλλά στην πραγματικότητα είναι αρκετά εύκολο να το καταλάβει κανείς: οι συνδεδεμένες ή εκτεταμένες υποκατηγορίες πρέπει να λειτουργούν όπως οι υπερκατηγορίες ή οι βασικές κατηγορίες τους. Αυτό σημαίνει ότι κάθε υποκατηγορία πρέπει να διατηρεί τις ιδιότητες της αντίστοιχης υπερκατηγορίας της μέσω κληρονομικότητας και αυτές οι ιδιότητες δεν πρέπει να αλλάζουν στην υποκατηγορία. Πρέπει να είναι αντικαταστάσιμες κατ’ αρχήν, εξ ου και η αρχή της υποκατάστασης. Οι υπερκατηγορίες, από την άλλη πλευρά, μπορούν να τροποποιηθούν.

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

Στην προγραμματιστική, η υπόθεση ότι παρόμοιες ή φαινομενικά πανομοιότυπες κλάσεις σχετίζονται ή εξαρτώνται η μία από την άλλη οδηγεί σε σφάλματα, παρεξηγήσεις και ασαφή κώδικα. Για αυτόν τον λόγο, στον προγραμματισμό, η κλάση «Rectangle» δεν είναι τετράγωνο και η κλάση «Square» δεν είναι ορθογώνιο. Και οι δύο είναι αποσυνδεδεμένες και υλοποιούνται ξεχωριστά. Χωρίς μια ολοκληρωμένη σύνδεση μεταξύ των κλάσεων, οι παρεξηγήσεις δεν μπορούν να οδηγήσουν σε σφάλματα μεταξύ των κλάσεων. Αυτό ενισχύει την ασφάλεια και τη σταθερότητα κατά την ανταλλαγή υλοποιήσεων σε υποκλάσεις ή υπερκλάσεις, χωρίς επιπτώσεις.

ISP: Αρχή διαχωρισμού διεπαφών

Σύμφωνα με τον Robert C. Martin στο «The Interface Segregation Principle» (Η αρχή του διαχωρισμού διεπαφών), η ISP ορίζεται ως εξής:

Quote

«Οι πελάτες δεν πρέπει να αναγκάζονται να εξαρτώνται από διεπαφές που δεν χρησιμοποιούν».

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

DIP: Αρχή αντιστροφής εξάρτησης

Σύμφωνα με τον Robert C. Martin στο «The Dependency Inversion Principle» (Η αρχή της αντιστροφής εξάρτησης), η πέμπτη και τελευταία από τις αρχές SOLID έχει ως εξής:

Quote

«Α. Τα υψηλού επιπέδου modules δεν πρέπει να εξαρτώνται από modules χαμηλού επιπέδου. Και τα δύο πρέπει να εξαρτώνται από αφαιρέσεις. Β. Οι αφαιρέσεις δεν πρέπει να εξαρτώνται από λεπτομέρειες».

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

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

Τι συμβαίνει αν δεν τηρούνται οι αρχές SOLID;

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

Οι συνέπειες του ακάθαρτου κώδικα ή της κακής συντήρησης κώδικα περιλαμβάνουν:

  • Code smell(κακός κώδικας): Όταν ο κώδικας δεν είναι γραμμένος σύμφωνα με τα απαραίτητα πρότυπα, αυτό μπορεί να προκαλέσει code smell ή «κακό κώδικα», οδηγώντας σε λειτουργικά σφάλματα και ασυμβίβαστα προγράμματα.
  • Σήψη κώδικα: Εάν δεν συντηρείται ή δεν επιδιορθώνεται με αναδιαμόρφωση ή δαπανηρή αναθεώρηση κώδικα, ο κώδικας μπορεί να «σαπίσει» μεταφορικά και να χάσει εντελώς τη λειτουργικότητά του. Ένας άλλος όρος για τον δυσανάγνωστο, περίπλοκο κώδικα είναι ο κώδικας σπαγγέτι.
  • Κίνδυνοι ασφαλείας: Τα προβλήματα που προκύπτουν δεν περιορίζονται σε διακοπές λειτουργίας, πολύπλοκη συντήρηση και προβλήματα συμβατότητας. Υπάρχουν επίσης κενά ασφαλείας που παρέχουν σε κακόβουλο λογισμικό ευκαιρίες να εκμεταλλευτεί τον κώδικα, συμπεριλαμβανομένων των εκμεταλλεύσεων zero-day.

Ποιος ανέπτυξε τις αρχές SOLID;

Η προέλευση των αρχών SOLID βρίσκεται σε διάφορες αρχές που εισήγαγε για πρώτη φορά ο Robert C. Martin («Uncle Bob»), ένας από τους πρωτοπόρους της ευέλικτης προγραμματισμού, το 2000 στο δοκίμιό του με τίτλο «Design Principles and Design Patterns» (Αρχές και πρότυπα σχεδιασμού). Οι αρχές SOLID επινοήθηκαν από τους Robert C. Martin, Bertrand Meyer και Barbara Liskov. Το ευκολομνημόνευτο ακρωνύμιο έγινε δημοφιλές από τον Michael Feathers, ο οποίος αναδιάταξε τα αρχικά γράμματα των πέντε βασικών αρχών σε μια ευκολομνημόνευτη σειρά.

Ποιες είναι οι παρόμοιες αρχές προγραμματισμού;

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

  • Αρχή DRY (Μην επαναλαμβάνεις τον εαυτό σου) για συναρτήσεις με μία και μοναδική αναπαράσταση
  • Αρχή KISS (Keep it simple, stupid - Κάν’ το απλό, ηλίθιε) για κώδικα κατασκευασμένο όσο το δυνατόν πιο απλά
Go to Main Menu