OCP — αρχές, ανοιχτότητα για επέκταση και κλειστότητα για τροποποίηση

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-05-11 Χρόνος ανάγνωσης: 9 λεπ

OCP (Open/Closed Principle) — η δεύτερη αρχή SOLID που ορίζει: οι οντότητες λογισμικού πρέπει να είναι ανοιχτές για επέκταση, αλλά κλειστές για τροποποίηση. Αυτή η αρχή, που διατυπώθηκε από τον Bertrand Meyer το 1988, επιτρέπει την προσθήκη νέας λειτουργικότητας χωρίς αλλαγή του υπάρχοντος κώδικα. Σύμφωνα με το βιβλίο του Robert C. Martin Clean Architecture (2017), η αρχή της ανοιχτότητας υλοποιείται μέσω αφαιρέσεων και πολυμορφισμού, ελαχιστοποιώντας τον κίνδυνο σφαλμάτων παλινδρόμησης.

Κύρια Σημεία

  • OCP — αρχή της ανοιχτότητας για επέκταση και κλειστότητας για τροποποίηση
  • Επέκταση υλοποιείται μέσω αφαιρέσεων, διεπαφών και πολυμορφισμού
  • Τροποποίηση του υπάρχοντος κώδικα απαγορεύεται — η νέα λειτουργικότητα προστίθεται χωρίς επεξεργασία των παλαιών κλάσεων
  • Πολυμορφισμός — ο βασικός μηχανισμός του OCP στις αντικειμενοστρεφείς γλώσσες
  • Παραβίαση του OCP οδηγεί σε αλυσιδωτές αλλαγές κατά την προσθήκη νέων απαιτήσεων

Τι είναι το OCP (Open/Closed Principle);

OCP (Open/Closed Principle) — η αρχή της ανοιχτότητας για επέκταση και κλειστότητας για τροποποίηση. Οι κλάσεις, οι ενότητες και οι συναρτήσεις πρέπει να σχεδιάζονται έτσι ώστε η νέα συμπεριφορά να προστίθεται χωρίς αλλαγή του πηγαίου κώδικά τους. Η επέκταση επιτυγχάνεται μέσω κληρονομικότητας, σύνθεσης ή υποκατάστασης υλοποιήσεων διεπαφών.

Ο Bertrand Meyer στο βιβλίο Object-Oriented Software Construction (1988) περιέγραψε για πρώτη φορά το OCP μέσω κληρονομικότητας: η βασική κλάση παραμένει αμετάβλητη και οι υποκλάσεις επεκτείνουν τη συμπεριφορά της. Η σύγχρονη ερμηνεία του OCP, που προτάθηκε από τον Robert C. Martin, βασίζεται στον πολυμορφισμό και τις διεπαφές: αντί για κληρονομικότητα, χρησιμοποιούνται αφηρημένες συμβάσεις.

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

Ο πολυμορφισμός ως βάση του OCP

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

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

Πώς να υλοποιήσετε την αρχή της ανοιχτότητας και κλειστότητας

Υλοποίηση του OCP ξεκινά με το διαχωρισμό της μεταβλητής συμπεριφοράς σε μια αφαίρεση. Αν στον κώδικα υπάρχει μια κατασκευή switch ή μια αλυσίδα if-else που ελέγχει τον τύπο του αντικειμένου — αυτό είναι ένα σήμα για εφαρμογή του OCP. Κάθε κλάδος της συνθήκης δυνητικά απαιτεί την προσθήκη ενός νέου κλάδου κατά την επέκταση.

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

Σημαντική σημείωση: η κλειστότητα για τροποποίηση δεν είναι απόλυτη. Αν η απαίτηση αλλαγής αφορά την ίδια την αφαίρεση ή τη σύμβαση — η αλλαγή είναι αναπόφευκτη. Το OCP προστατεύει από αλλαγές στις υλοποιήσεις, όχι στις συμβάσεις. Ένας καλός σχεδιασμός προϋποθέτει ότι οι συμβάσεις είναι σταθερές και οι υλοποιήσεις μεταβλητές.

Κατά την αξιολόγηση της συμβατότητας της αρχιτεκτονικής με το OCP, είναι χρήσιμο να κοιτάζετε τα σημεία επέκτασης. Κάθε σημείο όπου ο προγραμματιστής προσθέτει if-else ή switch για έναν νέο τύπο — υποψήφιος για αφαίρεση. Ένα σύστημα σχεδιασμένο σύμφωνα με το OCP έχει προβλέψιμα σημεία επέκτασης: διεπαφές με τεκμηρίωση “υλοποίησε αυτή τη διεπαφή για να προσθέσεις έναν νέο τύπο”. Στο Android, ένα τέτοιο παράδειγμα είναι το μοτίβο Factory μαζί με το ViewModelProvider.Factory — η προσθήκη ενός νέου τύπου ViewModel δεν απαιτεί αλλαγή των υπαρχόντων εργοστασίων.

Στρατηγικές και μοτίβα για το OCP

Τα πιο αποτελεσματικά μοτίβα για την τήρηση του OCP στην κινητή ανάπτυξη περιλαμβάνουν τα Strategy, Template Method, Decorator και Factory. Κάθε ένα λύνει το πρόβλημα της επέκτασης συμπεριφοράς χωρίς αλλαγή του υπάρχοντος κώδικα μέσω διαφορετικών μηχανισμών αντικειμενοστρεφούς σχεδιασμού.

Strategy επιτρέπει την αντικατάσταση αλγορίθμων εν κινήσει μέσω μιας κοινής διεπαφής. Στην ανάπτυξη iOS, οι στρατηγικές χρησιμοποιούνται για κινούμενα σχέδια και επικύρωση φορμών. Template Method ορίζει τον σκελετό του αλγορίθμου στη βασική κλάση, και οι υποκλάσεις παρακάμπτουν τα βήματα — κατάλληλο για οθόνες με κοινή δομή αλλά διαφορετικό περιεχόμενο.

Decorator προσθέτει δυναμικά συμπεριφορά σε ένα αντικείμενο χωρίς να αλλάζει την κλάση του. Στο Android, το Decorator εφαρμόζεται για το τύλιγμα του Repository με ένα επίπεδο προσωρινής αποθήκευσης ή καταγραφής. Factory Method δημιουργεί αντικείμενα μέσω μιας διεπαφής, επιτρέποντας στις υποκλάσεις να αποφασίσουν ποια κλάση θα δημιουργήσουν — η βάση της δημιουργίας εξαρτήσεων συμβατής με OCP.

Επιλογή στρατηγικής για κινητό έργο

Η επιλογή μοτίβου εξαρτάται από τη σταθερότητα της συμπεριφοράς που επεκτείνεται. Το Strategy είναι βέλτιστο όταν οι αλγόριθμοι αντικαθίστανται πλήρως. Template Method — όταν η δομή είναι σταθερή αλλά τα βήματα μεταβλητά. Decorator — όταν η επέκταση πρέπει να είναι διαφανής για τον πελάτη. Για τα περισσότερα σενάρια σε Android και iOS, αρκεί το Strategy + έγχυση εξαρτήσεων.

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

Παραδείγματα OCP σε κινητές εφαρμογές

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

kotlin
// Παραβίαση OCP: το switch απαιτεί αλλαγή για νέο σύστημα
class BadPaymentProcessor {
    fun process(type: String) {
        when (type) {
            "card" -> // επεξεργασία κάρτας
            "paypal" -> // επεξεργασία PayPal
        }
    }
}

// Σχεδιασμός συμβατός με OCP
interface PaymentMethod {
    fun pay(amount: Double)
}

class CardPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

class PayPalPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

// Νέο σύστημα — νέα κλάση, χωρίς αλλαγή του υπάρχοντος κώδικα
class ApplePayPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

Το παράδειγμα iOS με επικύρωση πεδίων κειμένου δείχνει την ίδια λογική μέσω των πρωτοκόλλων Swift:

swift
// Επικύρωση συμβατή με OCP
protocol ValidationRule {
    func validate(_ input: String) -> Bool
}

struct EmailRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.contains("@")
    }
}

struct PhoneRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.count == 11
    }
}

// Η προσθήκη νέου κανόνα δεν απαιτεί αλλαγή του κώδικα επικύρωσης
struct PasswordRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.count >= 8
    }
}

Το βασικό πλεονέκτημα του OCP σε αυτά τα παραδείγματα: η προσθήκη ApplePay ή PasswordRule δεν απαιτεί αλλαγή των υπαρχόντων κλάσεων. Ο κώδικας επεκτείνεται οριζόντια — μέσω νέων αρχείων, όχι με αλλαγή των παλαιών. Αυτό μειώνει τον κίνδυνο παλινδρόμησης και επιταχύνει την υλοποίηση νέας λειτουργικότητας.

Συνήθη λάθη κατά την παραβίαση του OCP

Η συνηθέστερη παραβίαση — η κατασκευή switch ή when με βάση τον τύπο του αντικειμένου. Κάθε φορά που προστίθεται ένας νέος τύπος, πρέπει να βρεθούν όλα αυτά τα switch στον κώδικα και να προστεθεί ένας νέος κλάδος. Ένα παραλειπόμενο switch — ένα σφάλμα χρόνου εκτέλεσης δύσκολο να εντοπιστεί στη φάση μεταγλώττισης.

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

Μια άλλη συνήθης παραβίαση — το God Adapter: RecyclerView.Adapter (Android) ή UITableViewDataSource (iOS) που επεξεργάζεται διαφορετικούς τύπους κελιών μέσω if-else. Κάθε νέος τύπος κελιού απαιτεί επέκταση του προσαρμογέα. Η λύση — ένας πολυμορφικός ViewHolder με μια κοινή μέθοδο bind, όπου κάθε τύπος κελιού είναι υπεύθυνος για τη δική του εμφάνιση.

Πώς να αποφύγετε την παραβίαση του OCP

Προληπτικά μέτρα περιλαμβάνουν: εγκατάλειψη του switch βάσει τύπου υπέρ του πολυμορφισμού, έγχυση εξαρτήσεων μέσω διεπαφών και εφαρμογή του μοτίβου Factory για δημιουργία αντικειμένων βάσει διαμόρφωσης. Ανάλυση κώδικα για “διακόπτες βάσει τύπου” — υποχρεωτικό μέρος της ανασκόπησης κώδικα σε ομάδες προσανατολισμένες στο OCP.

Αναδόμηση υπάρχουσας παραβίασης OCP εκτελείται μέσω Replace Conditional with Polymorphism: κάθε κλάδος της συνθήκης γίνεται μια ξεχωριστή κλάση με υλοποίηση μιας κοινής διεπαφής. Ο κώδικας πελάτη ξαναγράφεται για να λειτουργεί με τη διεπαφή, και η συγκεκριμένη υλοποίηση παρέχεται μέσω ενός εργοστασίου ή δοχείου DI.

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

Συχνές Ερωτήσεις

Το OCP σημαίνει ότι ο κώδικας δεν μπορεί να αλλάξει καθόλου;

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

Πώς σχετίζεται το OCP με το μοτίβο Strategy;

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

Μπορεί το OCP να τηρηθεί χωρίς διεπαφές;

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

Πώς επηρεάζει το OCP τη δοκιμή;

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

Πρέπει πάντα να επιδιώκουμε το OCP;

Όχι. Το OCP δικαιολογείται όταν η επέκταση της λειτουργικότητας είναι προβλέψιμη. Για σταθερό κώδικα που δεν προγραμματίζεται να επεκταθεί, η πρόσθετη αφαίρεση είναι περιττή. Το YAGNI (You Ain't Gonna Need It) — μια καλή αντιστάθμιση στο OCP: η αφαίρεση εισάγεται όταν εμφανίζεται μια δεύτερη παραλλαγή συμπεριφοράς, όχι εκ των προτέρων.

Σύνοψη

  • OCP (Open/Closed Principle) — αρχή της ανοιχτότητας για επέκταση και κλειστότητας για τροποποίηση
  • Επέκταση υλοποιείται μέσω διεπαφών, πολυμορφισμού και σύνθεσης αντί για κληρονομικότητα
  • Switch βάσει τύπου — το κύριο αντi-μοτίβο που παραβιάζει το OCP και απαιτεί αλλαγές σε κάθε νέο τύπο
  • Strategy και Template Method — τα κύρια μοτίβα για τήρηση του OCP σε κινητά έργα
  • Πολυμορφισμός αντικαθιστά τις δομές υπό όρους και καθιστά τον κώδικα επεκτάσιμο χωρίς τροποποίηση
  • Αναδόμηση παραβίασης OCP εκτελείται μέσω Replace Conditional with Polymorphism
  • YAGNI περιορίζει το OCP: η αφαίρεση εισάγεται όταν εμφανίζεται μια δεύτερη υλοποίηση, όχι εκ των προτέρων

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης