# Open/Closed Principle (OCP)

> Add new behavior by extending, not by editing — existing tested code stays untouched.

- **Category**: Solid
- **Subcategory**: principles
- **Canonical URL**: https://designpattern.fyi/solid/open/closed-principle-ocp/

---

## Description
**Intent**: Adding new features by modifying existing code risks breaking what already works. The fix is to make existing code closed to modification but open to extension through abstractions.

**Context**: Every new feature or variant means editing tested code, growing if-else chains, and adding switch cases. Each edit is a regression risk. New shapes, payment types, notification channels — all require changing the same class.

**Solution**: Design around abstractions — interfaces or abstract classes. New functionality arrives as a new implementation of an existing abstraction, not as an edit to the class. Add a Triangle by writing a new Triangle class, not by touching ShapeCalculator.



## Use Cases
You frequently add new variants or features. You want new capability without touching stable, tested code. You're building a plugin or extension architecture where third parties add new types.



## Implementation Example

```javascript
// Before: Violates OCP
class ShapeCalculator {
  calculateArea(shape) {
    if (shape.type === 'circle') {
      return Math.PI * shape.radius ** 2;
    } else if (shape.type === 'rectangle') {
      return shape.width * shape.height;
    }
    // Add new shapes here (modification)
  }
}

// After: OCP applied
class Shape {
  calculateArea() {
    throw new Error('Must implement calculateArea');
  }
}

class Circle extends Shape {
  constructor(radius) {
    super();
    this.radius = radius;
  }

  calculateArea() {
    return Math.PI * this.radius ** 2;
  }
}

class Rectangle extends Shape {
  constructor(width, height) {
    super();
    this.width = width;
    this.height = height;
  }

  calculateArea() {
    return this.width * this.height;
  }
}

// New shapes can be added without modifying existing code (extension)
```



## Trade-offs


### Advantages

- Stable, tested code is never touched when adding new cases

- Regression risk drops sharply — existing tests keep passing

- Naturally supports plugin and extension architectures

- New contributors can add features without understanding the whole system




### Considerations & Drawbacks

- Requires upfront abstraction investment — wrong abstractions are harder to reverse than if-else chains

- Over-engineered for truly one-off cases that will never vary

- More classes; more files to navigate







