OCP — principii, deschidere pentru extensie și închidere pentru modificare

Autor: IT Sectr Publicat: 2026-05-11 Timp de citire: 9 min

OCP (Open/Closed Principle) — al doilea principiu SOLID care definește: entitățile software trebuie să fie deschise pentru extensie, dar închise pentru modificare. Acest principiu, formulat de Bertrand Meyer în 1988, permite adăugarea de noi funcționalități fără modificarea codului existent. Conform cărții lui Robert C. Martin Clean Architecture (2017), principiul deschiderii este implementat prin abstractizări și polimorfism, minimizând riscul erorilor de regresie.

Principalele idei

  • OCP — principiul deschiderii pentru extensie și închiderii pentru modificare
  • Extinderea se realizează prin abstractizări, interfețe și polimorfism
  • Modificarea codului existent este interzisă — funcționalitatea nouă se adaugă fără a edita clasele vechi
  • Polimorfismul — mecanismul cheie al OCP în limbile orientate pe obiecte
  • Încălcarea OCP duce la modificări în cascadă la adăugarea de noi cerințe

Ce este OCP (Open/Closed Principle)?

OCP (Open/Closed Principle) — principiul deschiderii pentru extensie și închiderii pentru modificare. Clasele, modulele și funcțiile trebuie proiectate astfel încât un comportament nou să fie adăugat fără a modifica codul lor sursă. Extinderea se realizează prin moștenire, compoziție sau substituirea implementărilor de interfețe.

Bertrand Meyer în cartea Object-Oriented Software Construction (1988) a descris prima dată OCP prin moștenire: clasa de bază rămâne neschimbată, iar subclasele îi extind comportamentul. Interpretarea modernă a OCP, propusă de Robert C. Martin, se bazează pe polimorfism și interfețe: în locul moștenirii se folosesc contracte abstracte.

Diferența dintre abordări este semnificativă. Moștenirea creează o legătură rigidă între clasa de bază și cea derivată. Interfețele și compoziția oferă flexibilitate: implementarea este înlocuită fără a modifica codul client. OCP modern — este vorba despre abstractizare, nu despre moștenire.

Polimorfismul ca bază a OCP

OCP polimorfic folosește clase abstracte sau interfețe pentru a defini un contract. Codul client lucrează cu abstractizarea, fără a cunoaște implementarea concretă. O nouă funcționalitate se adaugă prin crearea unei noi clase care implementează aceeași interfață — fără nicio modificare a codului existent. Acest lucru face sistemul rezistent la schimbări și predictibil pentru extindere.

În dezvoltarea mobilă, această abordare este omniprezentă: șablonul Strategy permite înlocuirea algoritmilor (comprimarea imaginilor, cache, autentificare) printr-o interfață comună. Adăugarea unei noi strategii nu necesită modificarea codului care o folosește.

Cum se implementează principiul deschiderii și închiderii

Implementarea OCP începe prin separarea comportamentului variabil într-o abstractizare. Dacă în cod există o construcție switch sau un lanț if-else care verifică tipul obiectului — acesta este un semnal pentru aplicarea OCP. Fiecare ramură a condiției necesită potențial adăugarea unei noi ramuri la extindere.

Procesul de refactorizare conform OCP include trei pași: identificarea aspectului variabil (ceea ce poate fi extins), separarea lui într-o interfață sau clasă abstractă, rescrierea codului client pentru a lucra cu abstractizarea în locul clasei concrete. După aceasta, noua funcționalitate se adaugă fără a modifica clientul.

Precizare importantă: închiderea pentru modificare nu este absolută. Dacă cerința de modificare vizează însăși abstractizarea sau contractul — schimbarea este inevitabilă. OCP protejează împotriva modificărilor în implementări, nu în contracte. Un design bun presupune că contractele sunt stabile, iar implementările variabile.

La evaluarea compatibilității arhitecturii cu OCP este util să priviți punctele de extensie. Fiecare punct în care dezvoltatorul adaugă if-else sau switch pentru un tip nou — candidat pentru abstractizare. Un sistem proiectat conform OCP are puncte de extensie predictibile: interfețe cu documentația „implementează această interfață pentru a adăuga un tip nou“. În Android, un astfel de exemplu este șablonul Factory împreună cu ViewModelProvider.Factory — adăugarea unui nou tip de ViewModel nu necesită modificarea fabricilor existente.

Strategii și șabloane pentru OCP

Cele mai eficiente șabloane pentru respectarea OCP în dezvoltarea mobilă includ Strategy, Template Method, Decorator și Factory. Fiecare dintre ele rezolvă problema extinderii comportamentului fără modificarea codului existent prin diferite mecanisme de proiectare orientată pe obiecte.

Strategy permite înlocuirea algoritmilor din zbor printr-o interfață comună. În dezvoltarea iOS, strategiile sunt folosite pentru animații și validarea formularelor. Template Method definește scheletul algoritmului în clasa de bază, iar subclasele suprascriu pașii — potrivit pentru ecrane cu o structură comună, dar conținut diferit.

Decorator adaugă dinamic comportament unui obiect fără a-i modifica clasa. În Android, Decorator este aplicat pentru împachetarea Repository cu un strat de cache sau logare. Factory Method creează obiecte printr-o interfață, permițând subclaselor să decidă ce clasă să instanțieze — baza creării de dependențe compatibile cu OCP.

Alegerea strategiei pentru un proiect mobil

Alegerea șablonului depinde de stabilitatea comportamentului care se extinde. Strategy este optimă când algoritmii sunt înlocuiți complet. Template Method — când structura este fixă, dar pașii sunt variabili. Decorator — când extinderea trebuie să fie transparentă pentru client. Pentru majoritatea scenariilor în Android și iOS este suficient Strategy + injectarea dependențelor.

Aplicarea acestor șabloane fără OCP este posibilă tehnic, dar își pierde sensul. Tocmai OCP justifică de ce introducem un nivel suplimentar de abstractizare: pentru ca sistemul să crească fără a rescrie codul existent.

Exemple OCP în aplicațiile mobile

Să examinăm exemplul pe Android cu procesarea plăților. Fără OCP, fiecare sistem de plată nou necesită modificarea clasei de procesare. Cu OCP, se adaugă o nouă implementare a interfeței fără a edita codul existent.

kotlin
// Încălcarea OCP: switch necesită modificare pentru un sistem nou
class BadPaymentProcessor {
    fun process(type: String) {
        when (type) {
            "card" -> // procesarea cardului
            "paypal" -> // procesarea PayPal
        }
    }
}

// Design compatibil cu OCP
interface PaymentMethod {
    fun pay(amount: Double)
}

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

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

// Sistem nou — clasă nouă, fără modificarea codului existent
class ApplePayPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

Exemplul pe iOS cu validarea câmpurilor de text demonstrează aceeași logică prin protocoalele Swift:

swift
// Validare compatibilă cu 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
    }
}

// Adăugarea unei noi reguli nu necesită modificarea codului validatorului
struct PasswordRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.count >= 8
    }
}

Avantajul cheie al OCP în aceste exemple: adăugarea ApplePay sau PasswordRule nu necesită modificarea claselor existente. Codul se extinde orizontal — prin fișiere noi, nu prin modificarea celor vechi. Aceasta reduce riscul de regresie și accelerează implementarea noilor funcționalități.

Erori tipice la încălcarea OCP

Cea mai frecventă încălcare — construcția switch sau when în funcție de tipul obiectului. De fiecare dată când se adaugă un tip nou, trebuie găsite toate aceste switch-uri în cod și adăugată o nouă ramură. Un switch omis — o eroare în runtime dificil de depistat în faza de compilare.

În dezvoltarea mobilă, OCP este încălcat prin utilizarea claselor enum gigantice cu metode dependente de valoarea enum-ului. Adăugarea unui nou element enum necesită modificarea fiecărui switch din întregul proiect. Alternativa — polimorfismul printr-o interfață, unde fiecare tip își implementează propriul comportament.

O altă încălcare tipică — God Adapter: RecyclerView.Adapter (Android) sau UITableViewDataSource (iOS) care prin if-else procesează diferite tipuri de celule. Fiecare tip nou de celulă necesită extinderea adaptorului. Soluția — un ViewHolder polimorfic cu o metodă bind comună, unde fiecare tip de celulă este responsabil pentru propria afișare.

Cum să evitați încălcarea OCP

Măsuri preventive includ: renunțarea la switch pe tip în favoarea polimorfismului, injectarea dependențelor prin interfețe și aplicarea șablonului Factory pentru crearea obiectelor pe baza configurației. Analiza codului pentru „comutatoare pe tip“ — parte obligatorie a code review-ului în echipele orientate pe OCP.

Refactorizarea unei încălcări OCP existente se realizează prin Replace Conditional with Polymorphism: fiecare ramură a condiției devine o clasă separată cu implementarea unei interfețe comune. Codul client este rescris pentru a lucra cu interfața, iar implementarea concretă este furnizată printr-o fabrică sau container DI.

Este important de înțeles că OCP și polimorfismul nu rezolvă toate problemele de extindere. Dacă arhitectura a fost aleasă incorect, adăugarea unei noi funcționalități va necesita modificarea nu doar a implementărilor, ci și a contractelor. O arhitectură bună prezice direcțiile de extindere și plasează abstractizări exact în aceste puncte. Investiția în OCP se amortizează cu cât proiectul trăiește mai mult și cu cât cerințele pentru module specifice se schimbă mai des.

Întrebări frecvente

Înseamnă OCP că codul nu poate fi deloc modificat?

Nu. OCP interzice modificarea codului existent la adăugarea unei noi funcționalități care aparține aceleiași abstractizări. Modificarea contractului, corectarea erorilor și refactorizarea nu constituie încălcări ale OCP — principiul protejează împotriva modificărilor în cascadă la extindere.

Cum este legat OCP de șablonul Strategy?

Strategy — implementarea directă a OCP. Interfața strategiei definește contractul, clientul depinde de abstractizare, iar strategiile concrete implementează comportamentul variabil. Adăugarea unei noi strategii nu necesită modificarea clientului — aceasta este deschiderea pentru extensie cu închidere pentru modificare.

Se poate respecta OCP fără interfețe?

Da, prin moștenire și Template Method: clasa de bază definește scheletul algoritmului, subclasele suprascriu pașii. Totuși, moștenirea creează o legătură rigidă și este mai puțin flexibilă decât interfețele. În dezvoltarea modernă, interfețele și compoziția sunt considerate modalitatea preferată de implementare a OCP.

Cum influențează OCP testarea?

Codul compatibil cu OCP simplifică testarea: fiecare implementare a interfeței este testată izolat. Codul client este testat cu o implementare mock, ceea ce permite verificarea logicii fără legătura cu un comportament specific. Extinderea sistemului nu necesită rescrierea testelor existente.

Trebuie să urmărim întotdeauna OCP?

Nu. OCP este justificat când extinderea funcționalității este predictibilă. Pentru cod stabil care nu este planificat a fi extins, abstractizarea suplimentară este redundantă. YAGNI (You Ain't Gonna Need It) — un bun contrapunct la OCP: abstractizarea se introduce când apare o a doua variantă de comportament, nu preventiv.

Concluzii

  • OCP (Open/Closed Principle) — principiul deschiderii pentru extensie și închiderii pentru modificare
  • Extinderea se realizează prin interfețe, polimorfism și compoziție în locul moștenirii
  • Switch pe tip — principalul anti-pattern care încalcă OCP și necesită modificări la fiecare tip nou
  • Strategy și Template Method — principalele șabloane pentru respectarea OCP în proiectele mobile
  • Polimorfismul înlocuiește construcțiile condiționale și face codul extensibil fără modificare
  • Refactorizarea încălcării OCP se realizează prin Replace Conditional with Polymorphism
  • YAGNI limitează OCP: abstractizarea se introduce la apariția celei de-a doua implementări, nu din timp

Vom dezvolta o aplicație mobilă la cheie

IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.

Discutați proiectul

Citiți și