Last updated: Apr 29, 2026

Open-Closed

Classes should be open for extension but closed for modification. You should be able to add new behavior without changing existing code.

Every time you modify existing code, you risk breaking things that already work. If you design with interfaces from the start, adding new functionality means writing new classes — the old code never changes.

Example

This PaymentProcessor needs to be modified every time a new payment type is added:

class PaymentProcessor {
  process(paymentType: string, amount: number): void {
    if (paymentType === "credit") {
      // credit card logic
    } else if (paymentType === "paypal") {
      // paypal logic
    }
    // adding crypto means editing this method
  }
}

Use an interface so new payment types can be added without touching the processor:

interface PaymentMethod {
  process(amount: number): void;
}

class CreditCardPayment implements PaymentMethod {
  process(amount: number): void {
    // credit card logic
  }
}

class PayPalPayment implements PaymentMethod {
  process(amount: number): void {
    // paypal logic
  }
}

class CryptoPayment implements PaymentMethod {
  process(amount: number): void {
    // crypto logic
  }
}

class PaymentProcessor {
  process(method: PaymentMethod, amount: number): void {
    method.process(amount);
  }
}

Now adding cryptocurrency payments means creating a new class. The existing PaymentProcessor never changes.