KyoMel / Yogyakarta, Indonesia

Term 157157 / 344

Open-Closed Principle

Month
January 2026
Day
23
Source
2026/jan-term.md

Definition:

The Open-Closed Principle is one of the five SOLID principles of object-oriented design. It states:

“Software entities (classes, modules, functions) should be OPEN for extension but CLOSED for modification.”

In Simple Terms:

  • OPEN for Extension: You can add new functionality
  • CLOSED for Modification: You shouldn’t change existing, tested code

The Goal: Add new features without breaking existing code that already works.

Why It Matters

❌ Without OCP: Every new feature → Modify existing code → Risk breaking things → More bugs

✅ With OCP: New feature → Add new code → Existing code untouched → Nothing breaks Key Benefit: Change behavior by adding code, not editing code.

Example:

Payment Processing

// Abstract base class (or interface in TypeScript/Java)
class PaymentMethod {
  process(amount) {
    throw new Error('Must implement process method');
  }
}

// Concrete implementations (EXTENSIONS)
class CreditCardPayment extends PaymentMethod {
  process(amount) {
    console.log(`Processing $${amount} via Credit Card`);
    // Credit card specific logic
    this.validateCard();
    this.chargeCreditCard(amount);
    this.sendReceipt();
  }

  validateCard() { /* ... */ }
  chargeCreditCard(amount) { /* ... */ }
  sendReceipt() { /* ... */ }
}

class PayPalPayment extends PaymentMethod {
  process(amount) {
    console.log(`Processing $${amount} via PayPal`);
    // PayPal specific logic
    this.authenticatePayPal();
    this.chargePayPal(amount);
  }

  authenticatePayPal() { /* ... */ }
  chargePayPal(amount) { /* ... */ }
}

class BitcoinPayment extends PaymentMethod {
  process(amount) {
    console.log(`Processing $${amount} via Bitcoin`);
    // Bitcoin specific logic
    this.generateWalletAddress();
    this.waitForConfirmation(amount);
  }

  generateWalletAddress() { /* ... */ }
  waitForConfirmation(amount) { /* ... */ }
}

// PaymentProcessor is now CLOSED for modification
class PaymentProcessor {
  constructor() {
    this.paymentMethods = new Map();
  }

  // Register new payment methods (EXTENSION POINT)
  registerPaymentMethod(name, paymentMethod) {
    this.paymentMethods.set(name, paymentMethod);
  }

  // Process payment using registered method
  processPayment(amount, paymentType) {
    const paymentMethod = this.paymentMethods.get(paymentType);

    if (!paymentMethod) {
      throw new Error(`Payment method '${paymentType}' not registered`);
    }

    paymentMethod.process(amount);
  }
}

// Usage
const processor = new PaymentProcessor();

// Register payment methods (extending functionality)
processor.registerPaymentMethod('credit_card', new CreditCardPayment());
processor.registerPaymentMethod('paypal', new PayPalPayment());
processor.registerPaymentMethod('bitcoin', new BitcoinPayment());

// Process payments
processor.processPayment(100, 'credit_card');
processor.processPayment(50, 'paypal');
processor.processPayment(0.002, 'bitcoin');

Keep reading