OCP

How can you add new features without touching existing code? Master the Open-Closed Principle to build future-proof software.

April 28, 20264 min read2 / 6

The Open-Closed Principle (OCP) states that software entities (classes, modules, functions) should be Open for Extension but Closed for Modification.

The Essentials

The "Add, Don't Change" guide:

  1. Extension: You should be able to add new behavior by adding new code.
  2. Immutability: Existing code should remain untouched and "closed" to prevent new bugs.
  3. Abstraction: Interfaces and Abstract Classes are the primary tools used to achieve OCP.
  4. Safety: By not touching proven, working code, you ensure that new features don't break old ones.

The Lego Analogy

Imagine you have a Lego spaceship.

  1. Open for Extension: You want to add a laser cannon. You find a connector point and "click" the cannon into place.
  2. Closed for Modification: You didn't have to take apart the spaceship's engine or rewrite the manual to add the cannon.

This is OCP in action. You add the "Laser" behavior by extending the base structure, not by rebuilding it.

OCP in Action: The Payment Problem

Modification Trap

Adding a new payment type requires modifying the process method. This "opens" the class for bugs.

class Payment {
  process(type) {
    if (type == "UPI") { .. }
    else if (type == "CC") { .. }
  }
}

Every new feature requires code "surgery." This risk of breaking existing logic grows over time.

Extension Ready

We use an interface. Adding a new payment type simply means adding a new class. No existing code is touched.

interface Payment { pay(); }

class UPI implements Payment {
  pay() { /* ... */ }
}

class CC implements Payment { .. }

The system is "Open" for new types but "Closed" to modifications of the core processor.

Code Implementation: Adding Features via Extension

Here is how you implement this "Add, Don't Change" strategy:

interface PaymentMethod { process(): void; } class UPIPayment implements PaymentMethod { process() { console.log("Processing UPI..."); } } class CardPayment implements PaymentMethod { process() { console.log("Processing Credit Card..."); } } // The Processor is CLOSED to modification class PaymentProcessor { process(method: PaymentMethod) { method.process(); } } // Want a new Crypto payment? Just add a new class! class CryptoPayment implements PaymentMethod { process() { console.log("Processing Crypto..."); } }

Why It Matters: The "Manager Monday"

If your manager asks for a new feature on Monday, OCP allows you to:

  1. Ship Faster: You only write new code; you don't spend hours re-testing the old code.
  2. Sleep Better: You know for a fact that your new UPI logic cannot break the existing Credit Card logic because they don't share the same file.

By mastering OCP, you build systems that grow naturally over time, rather than becoming a "House of Cards" that collapses every time you add a new room.

Next, we'll dive into the Liskov Substitution Principle and learn how to avoid the "Bird & Ostrich" trap.


Practice what you just read.

OCP: Extensible Area Calculator
1 exercise