OCP — principes, openheid voor uitbreiding en geslotenheid voor modificatie

Auteur: IT Sectr Gepubliceerd: 2026-05-11 Leestijd: 9 min

OCP (Open/Closed Principle) — het tweede SOLID-principe dat bepaalt: software-entiteiten moeten open zijn voor uitbreiding, maar gesloten voor modificatie. Dit principe, geformuleerd door Bertrand Meyer in 1988, maakt het mogelijk om nieuwe functionaliteit toe te voegen zonder bestaande code te wijzigen. Volgens het boek van Robert C. Martin Clean Architecture (2017), wordt het principe van openheid geïmplementeerd via abstracties en polymorfisme, waardoor het risico op regressiefouten wordt geminimaliseerd.

Belangrijkste punten

  • OCP — principe van openheid voor uitbreiding en geslotenheid voor modificatie
  • Uitbreiding wordt gerealiseerd via abstracties, interfaces en polymorfisme
  • Modificatie van bestaande code is verboden — nieuwe functionaliteit wordt toegevoegd zonder oude klassen te bewerken
  • Polymorfisme — het sleutelmechanisme van OCP in objectgeoriënteerde talen
  • Schending van OCP leidt tot cascading changes bij het toevoegen van nieuwe vereisten

Wat is OCP (Open/Closed Principle)?

OCP (Open/Closed Principle) — het principe van openheid voor uitbreiding en geslotenheid voor modificatie. Klassen, modules en functies moeten zo worden ontworpen dat nieuw gedrag wordt toegevoegd zonder hun broncode te wijzigen. Uitbreiding wordt bereikt via overerving, compositie of substitutie van interface-implementaties.

Bertrand Meyer beschreef OCP voor het eerst in het boek Object-Oriented Software Construction (1988) via overerving: de basisklasse blijft ongewijzigd en subklassen breiden het gedrag ervan uit. De moderne interpretatie van OCP, voorgesteld door Robert C. Martin, is gebaseerd op polymorfisme en interfaces: in plaats van overerving worden abstracte contracten gebruikt.

Het verschil tussen de benaderingen is significant. Overerving creëert een starre koppeling tussen de basis- en afgeleide klasse. Interfaces en compositie bieden flexibiliteit: de implementatie wordt vervangen zonder de clientcode te wijzigen. Moderne OCP — gaat over abstractie, niet over overerving.

Polymorfisme als basis van OCP

Polymorfe OCP gebruikt abstracte klassen of interfaces om een contract te definiëren. Clientcode werkt met de abstractie, zonder de concrete implementatie te kennen. Nieuwe functionaliteit wordt toegevoegd door een nieuwe klasse te maken die dezelfde interface implementeert — zonder enige wijziging in bestaande code. Dit maakt het systeem bestand tegen veranderingen en voorspelbaar voor uitbreiding.

In mobiele ontwikkeling is deze benadering alomtegenwoordig: het Strategy-patroon maakt het mogelijk om algoritmen (beeldcompressie, caching, authenticatie) te vervangen via een gemeenschappelijke interface. Het toevoegen van een nieuwe strategie vereist geen wijziging van de code die deze gebruikt.

Hoe het principe van openheid en geslotenheid te implementeren

Implementatie van OCP begint met het scheiden van variabel gedrag in een abstractie. Als er in de code een switch-constructie of een if-else-keten is die het objecttype controleert — is dit een signaal om OCP toe te passen. Elke voorwaardtak vereist potentieel het toevoegen van een nieuwe tak bij uitbreiding.

Het refactoringproces volgens OCP omvat drie stappen: het identificeren van het variabele aspect (wat kan worden uitgebreid), het scheiden ervan in een interface of abstracte klasse, en het herschrijven van de clientcode om met de abstractie te werken in plaats van de concrete klasse. Daarna wordt nieuwe functionaliteit toegevoegd zonder de client te wijzigen.

Belangrijke opmerking: geslotenheid voor modificatie is niet absoluut. Als de wijzigingsvereiste betrekking heeft op de abstractie zelf of het contract — is verandering onvermijdelijk. OCP beschermt tegen wijzigingen in implementaties, niet in contracten. Een goed ontwerp veronderstelt dat contracten stabiel zijn en implementaties variabel.

Bij het beoordelen van de architectuurcompatibiliteit met OCP is het nuttig om naar uitbreidingspunten te kijken. Elk punt waar de ontwikkelaar if-else of switch toevoegt voor een nieuw type — een kandidaat voor abstractie. Een systeem dat volgens OCP is ontworpen, heeft voorspelbare uitbreidingspunten: interfaces met documentatie „implementeer deze interface om een nieuw type toe te voegen“. In Android is een voorbeeld hiervan het Factory-patroon in combinatie met ViewModelProvider.Factory — het toevoegen van een nieuw ViewModel-type vereist geen wijziging van bestaande fabrieken.

Strategieën en patronen voor OCP

De meest effectieve patronen voor het naleven van OCP in mobiele ontwikkeling omvatten Strategy, Template Method, Decorator en Factory. Elk lost het probleem van gedragsuitbreiding zonder bestaande code te wijzigen op via verschillende mechanismen van objectgeoriënteerd ontwerpen.

Strategy maakt het mogelijk om algoritmen ter plekke te vervangen via een gemeenschappelijke interface. In iOS-ontwikkeling worden strategieën gebruikt voor animaties en formuliervalidatie. Template Method definieert het skelet van het algoritme in de basisklasse, en subklassen overschrijven de stappen — geschikt voor schermen met een gemeenschappelijke structuur maar verschillende inhoud.

Decorator voegt dynamisch gedrag toe aan een object zonder de klasse ervan te wijzigen. In Android wordt Decorator toegepast voor het inpakken van Repository met een cache- of loggingslaag. Factory Method creëert objecten via een interface, waardoor subklassen kunnen beslissen welke klasse ze moeten instantiëren — de basis van OCP-compatibele afhankelijkheidscreatie.

Strategiekeuze voor een mobiel project

De keuze van het patroon hangt af van de stabiliteit van het uit te breiden gedrag. Strategy is optimaal wanneer algoritmen volledig worden vervangen. Template Method — wanneer de structuur vastligt maar de stappen variabel zijn. Decorator — wanneer de uitbreiding transparant moet zijn voor de client. Voor de meeste scenario's in Android en iOS is Strategy + afhankelijkheidsinjectie voldoende.

Het toepassen van deze patronen zonder OCP is technisch mogelijk, maar verliest zijn betekenis. Juist OCP rechtvaardigt waarom we een extra abstractieniveau introduceren: zodat het systeem kan groeien zonder bestaande code te herschrijven.

Voorbeelden van OCP in mobiele apps

Laten we het Android-voorbeeld met betalingsverwerking bekijken. Zonder OCP vereist elk nieuw betalingssysteem wijziging van de verwerkingsklasse. Met OCP wordt een nieuwe interface-implementatie toegevoegd zonder bestaande code te bewerken.

kotlin
// OCP-schending: switch vereist wijziging voor een nieuw systeem
class BadPaymentProcessor {
    fun process(type: String) {
        when (type) {
            "card" -> // kaartverwerking
            "paypal" -> // PayPal-verwerking
        }
    }
}

// OCP-compatibel ontwerp
interface PaymentMethod {
    fun pay(amount: Double)
}

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

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

// Nieuw systeem — nieuwe klasse, zonder bestaande code te wijzigen
class ApplePayPayment : PaymentMethod {
    override fun pay(amount: Double) { }
}

Het iOS-voorbeeld met tekstveldvalidatie toont dezelfde logica via Swift-protocollen:

swift
// OCP-compatibele validatie
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
    }
}

// Toevoegen van een nieuwe regel vereist geen wijziging van de validatorcode
struct PasswordRule: ValidationRule {
    func validate(_ input: String) -> Bool {
        return input.count >= 8
    }
}

Het belangrijkste voordeel van OCP in deze voorbeelden: het toevoegen van ApplePay of PasswordRule vereist geen wijziging van bestaande klassen. Code breidt zich horizontaal uit — via nieuwe bestanden, niet door oude bestanden te wijzigen. Dit vermindert het risico op regressie en versnelt de implementatie van nieuwe functionaliteit.

Veelvoorkomende fouten bij schending van OCP

De meest voorkomende schending — de switch- of when-constructie op basis van het objecttype. Elke keer dat een nieuw type wordt toegevoegd, moeten al deze switches in de code worden gevonden en moet een nieuwe tak worden toegevoegd. Een gemiste switch — een runtime-fout die moeilijk te detecteren is in de compilatiefase.

In mobiele ontwikkeling wordt OCP geschonden bij het gebruik van gigantische enum-klassen met methoden die afhankelijk zijn van de enum-waarde. Het toevoegen van een nieuw enum-element vereist wijziging van elke switch in het hele project. Het alternatief — polymorfisme via een interface, waarbij elk type zijn eigen gedrag implementeert.

Een andere veelvoorkomende schending — God Adapter: RecyclerView.Adapter (Android) of UITableViewDataSource (iOS) die via if-else verschillende celtypen verwerkt. Elk nieuw celtype vereist uitbreiding van de adapter. De oplossing — een polymorfe ViewHolder met een gemeenschappelijke bind-methode, waarbij elk celtype verantwoordelijk is voor zijn eigen weergave.

Hoe OCP-schending te voorkomen

Preventieve maatregelen omvatten: afzien van switch op type ten gunste van polymorfisme, afhankelijkheidsinjectie via interfaces en toepassing van het Factory-patroon voor het maken van objecten op basis van configuratie. Analyse van code op „type-schakelaars“ — een verplicht onderdeel van code-review in OCP-georiënteerde teams.

Refactoring van bestaande OCP-schending wordt uitgevoerd via Replace Conditional with Polymorphism: elke voorwaardtak wordt een aparte klasse met implementatie van een gemeenschappelijke interface. De clientcode wordt herschreven om met de interface te werken, en de concrete implementatie wordt geleverd via een fabriek of DI-container.

Het is belangrijk te begrijpen dat OCP en polymorfisme niet alle uitbreidingsproblemen oplossen. Als de architectuur verkeerd is gekozen, zal het toevoegen van nieuwe functionaliteit niet alleen wijziging van implementaties maar ook van contracten vereisen. Een goede architectuur voorspelt de richtingen van uitbreiding en plaatst abstracties precies op die punten. De investering in OCP werpt zijn vruchten af naarmate het project langer leeft en de vereisten voor specifieke modules vaker veranderen.

Veelgestelde vragen

Betekent OCP dat code helemaal niet gewijzigd kan worden?

Nee. OCP verbiedt het wijzigen van bestaande code bij het toevoegen van nieuwe functionaliteit die tot dezelfde abstractie behoort. Het wijzigen van het contract, het corrigeren van bugs en refactoring zijn geen schendingen van OCP — het principe beschermt tegen cascading changes bij uitbreiding.

Hoe is OCP gerelateerd aan het Strategy-patroon?

Strategy — een directe implementatie van OCP. De interface van de strategie definieert het contract, de client is afhankelijk van de abstractie, en de concrete strategieën implementeren variabel gedrag. Het toevoegen van een nieuwe strategie vereist geen wijziging van de client — dit is openheid voor uitbreiding met geslotenheid voor modificatie.

Kan OCP zonder interfaces worden nageleefd?

Ja, via overerving en Template Method: de basisklasse definieert het skelet van het algoritme, subklassen overschrijven de stappen. Overerving creëert echter een starre koppeling en is minder flexibel dan interfaces. In moderne ontwikkeling worden interfaces en compositie beschouwd als de voorkeursmanier om OCP te implementeren.

Hoe beïnvloedt OCP het testen?

OCP-compatibele code vereenvoudigt het testen: elke interface-implementatie wordt geïsoleerd getest. Clientcode wordt getest met een mock-implementatie, waardoor de logica kan worden geverifieerd zonder koppeling aan specifiek gedrag. Uitbreiding van het systeem vereist geen herschrijven van bestaande tests.

Moeten we altijd naar OCP streven?

Nee. OCP is gerechtvaardigd wanneer uitbreiding van functionaliteit voorspelbaar is. Voor stabiele code die niet gepland is om te worden uitgebreid, is extra abstractie overbodig. YAGNI (You Ain't Gonna Need It) — een goed tegenwicht voor OCP: abstractie wordt geïntroduceerd wanneer een tweede gedragsvariant verschijnt, niet preventief.

Samenvatting

  • OCP (Open/Closed Principle) — principe van openheid voor uitbreiding en geslotenheid voor modificatie
  • Uitbreiding wordt gerealiseerd via interfaces, polymorfisme en compositie in plaats van overerving
  • Switch op type — het belangrijkste anti-patroon dat OCP schendt en bij elk nieuw type wijzigingen vereist
  • Strategy en Template Method — de belangrijkste patronen voor het naleven van OCP in mobiele projecten
  • Polymorfisme vervangt conditionele constructies en maakt code uitbreidbaar zonder wijziging
  • Refactoring van OCP-schending wordt uitgevoerd via Replace Conditional with Polymorphism
  • YAGNI beperkt OCP: abstractie wordt geïntroduceerd bij het verschijnen van een tweede implementatie, niet vooraf

We ontwikkelen een mobiele applicatie turnkey

IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.

Bespreek het project

Lees ook