Catalog / SOLID Principles / Open/Closed Principle (OCP)
SOLID

Open/Closed Principle (OCP)

Software entities should be open for extension, but closed for modification.

Intent & Objective

You should be able to add new functionality to a system without editing existing, tested source code. Extend behavior by adding new classes, strategies, or functions instead of modifying existing switch/if-else blocks.

πŸ‘₯ Real-World Human Analogies & Social Roles
2 Intuitive Scenarios
Computer Motherboard & USB Ports Hardware Architecture

"You can plug in new microphones, cameras, or external SSDs into standard USB ports (open for extension) without soldering wires onto the motherboard circuits (closed for modification)."

Wall Electrical Outlets Electrical Grid

"Power strips and standard AC plugs allow any new household appliance to receive electricity without rewiring the building walls."

The Problem

When new features are added by editing existing conditionals (e.g. `switch (paymentType)`), you risk introducing regressions into existing payment methods, violating tests, and generating massive merge conflicts.

The Solution

Program to abstractions or interfaces. Create a contract (interface or function signature) and write new implementations for new requirements.

Key Participants & Architectural Roles

Abstract Interface / Strategy
Declares the contract that client code relies upon
Concrete Implementations
Provide specific implementations (e.g., CreditCard, PayPal, Crypto)
Context / Client
Works only through the abstraction without knowing concrete types

Code Samples (Traditional OOP vs Functional Programming)

Available in C++, Python, and Java

Paradigm Contrast: Traditional OOP vs Functional / Data-Oriented

In OOP, OCP is achieved through polymorphism, inheritance, and interfaces (Strategy Pattern). In Functional Programming, OCP is the natural consequence of Higher-Order Functions: functions accept behavior as parameters (lambdas or function pointers), making the function open to any behavior without altering its implementation.

Advantages

  • βœ“ Eliminates regression bugs in existing, verified code
  • βœ“ Plug-and-play architecture enables new features to be added seamlessly
  • βœ“ Aligns with Strategy and Factory design patterns

Trade-offs

  • βœ— Introduces indirection and higher initial abstraction levels
  • βœ— Over-anticipating future variations can lead to premature abstraction

When to Apply

  • β†’ When you find yourself repeatedly adding `case` statements to a switch block whenever a new type arises
  • β†’ When building plugin systems or modules expected to grow over time
  • β†’ In payment processing, shipping calculation, authentication, or notification engines

When to Avoid

  • ! When business logic is fixed and will never change
  • ! For simple 2-way toggle states (e.g. boolean isEnabled)