OCP — principy, otevřenost pro rozšíření a uzavřenost pro modifikaci

Autor: IT Sectr Publikováno: 2026-05-11 Doba čtení: 9 min

OCP (Open/Closed Principle) — druhý princip SOLID, který stanovuje: softwarové entity by měly být otevřené pro rozšíření, ale uzavřené pro modifikaci. Tento princip, formulovaný Bertrandem Meyerem v roce 1988, umožňuje přidávat novou funkcionalitu bez změny existujícího kódu. Podle knihy Roberta C. Martina Clean Architecture (2017), je princip otevřenosti implementován prostřednictvím abstrakcí a polymorfismu, čímž se minimalizuje riziko regresních chyb.

Hlavní body

  • OCP — princip otevřenosti pro rozšíření a uzavřenosti pro modifikaci
  • Rozšíření je realizováno prostřednictvím abstrakcí, rozhraní a polymorfismu
  • Modifikace existujícího kódu je zakázána — nová funkcionalita se přidává bez úprav starých tříd
  • Polymorfismus — klíčový mechanismus OCP v objektově orientovaných jazycích
  • Porušení OCP vede k řetězovým změnám při přidávání nových požadavků

Co je OCP (Open/Closed Principle)?

OCP (Open/Closed Principle) — princip otevřenosti pro rozšíření a uzavřenosti pro modifikaci. Třídy, moduly a funkce by měly být navrženy tak, aby nové chování bylo přidáno bez změny jejich zdrojového kódu. Rozšíření je dosaženo prostřednictvím dědičnosti, kompozice nebo substituce implementací rozhraní.

Bertrand Meyer v knize Object-Oriented Software Construction (1988) poprvé popsal OCP prostřednictvím dědičnosti: základní třída zůstává nezměněna a podtřídy rozšiřují její chování. Moderní výklad OCP, navržený Robertem C. Martinem, se opírá o polymorfismus a rozhraní: místo dědičnosti se používají abstraktní kontrakty.

Rozdíl mezi přístupy je významný. Dědičnost vytváří pevné propojení mezi základní a odvozenou třídou. Rozhraní a kompozice poskytují flexibilitu: implementace je nahrazena bez změny klientského kódu. Moderní OCP — je o abstrakci, ne o dědičnosti.

Polymorfismus jako základ OCP

Polymorfní OCP používá abstraktní třídy nebo rozhraní k definování kontraktu. Klientský kód pracuje s abstrakcí, aniž by znal konkrétní implementaci. Nová funkcionalita se přidává vytvořením nové třídy implementující stejné rozhraní — bez jakékoli změny existujícího kódu. To činí systém odolným vůči změnám a předvídatelným pro rozšíření.

V mobilním vývoji je tento přístup všudypřítomný: vzor Strategy umožňuje nahrazovat algoritmy (komprese obrázků, ukládání do mezipaměti, autentizace) prostřednictvím společného rozhraní. Přidání nové strategie nevyžaduje změnu kódu, který ji používá.

Jak implementovat princip otevřenosti a uzavřenosti

Implementace OCP začíná oddělením proměnlivého chování do abstrakce. Pokud je v kódu konstrukce switch nebo řetězec if-else kontrolující typ objektu — to je signál k aplikaci OCP. Každá větev podmínky potenciálně vyžaduje přidání nové větve při rozšíření.

Proces refaktorování podle OCP zahrnuje tři kroky: identifikovat proměnlivý aspekt (co může být rozšířeno), oddělit jej do rozhraní nebo abstraktní třídy, přepsat klientský kód pro práci s abstrakcí namísto konkrétní třídy. Poté je nová funkcionalita přidána bez změny klienta.

Důležité upřesnění: uzavřenost pro modifikaci není absolutní. Pokud se požadavek na změnu týká samotné abstrakce nebo kontraktu — změna je nevyhnutelná. OCP chrání před změnami v implementacích, ne v kontraktech. Dobrý design předpokládá, že kontrakty jsou stabilní a implementace proměnlivé.

Při hodnocení kompatibility architektury s OCP je užitečné dívat se na body rozšíření. Každý bod, kde vývojář přidává if-else nebo switch pro nový typ — kandidát na abstrakci. Systém navržený podle OCP má předvídatelné body rozšíření: rozhraní s dokumentací „implementuj toto rozhraní pro přidání nového typu“. V Androidu je takovým příkladem vzor Factory ve spojení s ViewModelProvider.Factory — přidání nového typu ViewModel nevyžaduje změnu existujících továren.

Strategie a vzory pro OCP

Nejefektivnější vzory pro dodržování OCP v mobilním vývoji zahrnují Strategy, Template Method, Decorator a Factory. Každý z nich řeší problém rozšíření chování bez modifikace existujícího kódu prostřednictvím různých mechanismů objektově orientovaného návrhu.

Strategy umožňuje nahrazovat algoritmy za běhu prostřednictvím společného rozhraní. Ve vývoji pro iOS se strategie používají pro animace a validaci formulářů. Template Method definuje kostru algoritmu v základní třídě a podtřídy přepisují kroky — vhodné pro obrazovky se společnou strukturou, ale odlišným obsahem.

Decorator dynamicky přidává chování objektu bez změny jeho třídy. V Androidu se Decorator aplikuje na obalení Repository vrstvou cache nebo logování. Factory Method vytváří objekty prostřednictvím rozhraní a umožňuje podtřídám rozhodnout, kterou třídu instanciovat — základ vytváření závislostí kompatibilního s OCP.

Výběr strategie pro mobilní projekt

Výběr vzoru závisí na stabilitě rozšiřovaného chování. Strategy je optimální, když jsou algoritmy zcela nahrazovány. Template Method — když je struktura pevná, ale kroky proměnlivé. Decorator — když má být rozšíření transparentní pro klienta. Pro většinu scénářů v Androidu a iOS stačí Strategy + vkládání závislostí.

Aplikace těchto vzorů bez OCP je technicky možná, ale ztrácí smysl. Právě OCP ospravedlňuje, proč zavádíme další úroveň abstrakce: aby systém mohl růst bez přepisování existujícího kódu.

Příklady OCP v mobilních aplikacích

Podívejme se na příklad z Androidu se zpracováním plateb. Bez OCP každý nový platební systém vyžaduje změnu zpracovatelské třídy. S OCP se přidá nová implementace rozhraní bez úpravy existujícího kódu.

kotlin
// Porušení OCP: switch vyžaduje změnu pro nový systém
class BadPaymentProcessor {
    fun process(type: String) {
        when (type) {
            "card" -> // zpracování karty
            "paypal" -> // zpracování PayPal
        }
    }
}

// Design kompatibilní s OCP
interface PaymentMethod {
    fun pay(amount: Double)
}

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

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

// Nový systém — nová třída, bez změny existujícího kódu
class ApplePayPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

Příklad z iOS s validací textových polí demonstruje stejnou logiku prostřednictvím protokolů Swift:

swift
// Validace kompatibilní s 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
    }
}

// Přidání nového pravidla nevyžaduje změnu kódu validátoru
struct PasswordRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.count >= 8
    }
}

Klíčová výhoda OCP v těchto příkladech: přidání ApplePay nebo PasswordRule nevyžaduje změnu existujících tříd. Kód se rozšiřuje horizontálně — prostřednictvím nových souborů, nikoli změnou starých. To snižuje riziko regrese a urychluje zavádění nové funkcionality.

Typické chyby při porušení OCP

Nejčastější porušení — konstrukce switch nebo when podle typu objektu. Při každém přidání nového typu je třeba najít všechny takové switch v kódu a přidat novou větev. Vynechaný switch — chyba za běhu, kterou je obtížné odhalit ve fázi kompilace.

V mobilním vývoji je OCP porušováno při použití obřích enum tříd s metodami závislými na hodnotě enum. Přidání nového prvku enum vyžaduje změnu každého switch v celém projektu. Alternativou je polymorfismus prostřednictvím rozhraní, kde každý typ implementuje své vlastní chování.

Dalším typickým porušením je God Adapter: RecyclerView.Adapter (Android) nebo UITableViewDataSource (iOS), který prostřednictvím if-else zpracovává různé typy buněk. Každý nový typ buňky vyžaduje rozšíření adaptéru. Řešením je polymorfní ViewHolder se společnou metodou bind, kde každý typ buňky odpovídá za své vlastní zobrazení.

Jak se vyhnout porušení OCP

Preventivní opatření zahrnují: opuštění switch podle typu ve prospěch polymorfismu, vkládání závislostí prostřednictvím rozhraní a aplikaci vzoru Factory pro vytváření objektů podle konfigurace. Analýza kódu na „přepínače podle typu“ — povinná součást code review v OCP-orientovaných týmech.

Refaktorování existujícího porušení OCP se provádí pomocí Replace Conditional with Polymorphism: každá větev podmínky se stává samostatnou třídou s implementací společného rozhraní. Klientský kód je přepsán pro práci s rozhraním a konkrétní implementace je dodávána prostřednictvím továrny nebo DI kontejneru.

Je důležité pochopit, že OCP a polymorfismus neřeší všechny problémy rozšiřování. Pokud je architektura zvolena nesprávně, přidání nové funkcionality bude vyžadovat změnu nejen implementací, ale i kontraktů. Dobrá architektura předvídá směry rozšíření a umisťuje abstrakce právě v těchto bodech. Investice do OCP se vyplácí tím více, čím déle projekt žije a čím častěji se mění požadavky na konkrétní moduly.

Často kladené otázky

Znamená OCP, že kód nelze vůbec měnit?

Ne. OCP zakazuje změnu existujícího kódu při přidávání nové funkcionality patřící ke stejné abstrakci. Změna kontraktu, oprava chyb a refaktorování nejsou porušením OCP — princip chrání před řetězovými změnami při rozšiřování.

Jak OCP souvisí se vzorem Strategy?

Strategy — přímá implementace OCP. Rozhraní strategie definuje kontrakt, klient závisí na abstrakci a konkrétní strategie implementují proměnlivé chování. Přidání nové strategie nevyžaduje změnu klienta — to je otevřenost pro rozšíření při uzavřenosti pro modifikaci.

Lze dodržovat OCP bez rozhraní?

Ano, prostřednictvím dědičnosti a Template Method: základní třída definuje kostru algoritmu, podtřídy přepisují kroky. Dědičnost však vytváří pevné propojení a je méně flexibilní než rozhraní. V moderním vývoji jsou rozhraní a kompozice považovány za preferovaný způsob implementace OCP.

Jak OCP ovlivňuje testování?

Kód kompatibilní s OCP zjednodušuje testování: každá implementace rozhraní je testována izolovaně. Klientský kód je testován s mock implementací, což umožňuje ověřit logiku bez vazby na konkrétní chování. Rozšíření systému nevyžaduje přepisování existujících testů.

Je vždy nutné usilovat o OCP?

Ne. OCP je ospravedlnitelný, když je rozšíření funkcionality předvídatelné. Pro stabilní kód, který není plánován k rozšiřování, je další abstrakce zbytečná. YAGNI (You Ain't Gonna Need It) — dobrá protiváha OCP: abstrakce se zavádí, když se objeví druhá varianta chování, nikoli předem.

Shrnutí

  • OCP (Open/Closed Principle) — princip otevřenosti pro rozšíření a uzavřenosti pro modifikaci
  • Rozšíření je realizováno prostřednictvím rozhraní, polymorfismu a kompozice místo dědičnosti
  • Switch podle typu — hlavní anti-vzor porušující OCP a vyžadující úpravy při každém novém typu
  • Strategy a Template Method — hlavní vzory pro dodržování OCP v mobilních projektech
  • Polymorfismus nahrazuje podmíněné konstrukce a činí kód rozšiřitelným bez modifikace
  • Refaktorování porušení OCP se provádí pomocí Replace Conditional with Polymorphism
  • YAGNI omezuje OCP: abstrakce se zavádí při objevení druhé implementace, nikoli předem

Vyvineme mobilní aplikaci na klíč

IT Sectr vytváří aplikace pro iOS a Android pro startupy a podniky od roku 2017. Poradíme vám a navrhneme nejlepší řešení.

Prodiskutovat projekt

Přečtěte si také