CodeOath
← All posts
Architecture & Patterns80 min total · 26 parts

ACID, SOLID, and Common Design Patterns: A Software Design Reference

Contents — Part 8 of 26: Open/Closed Principle
Part 8 of 26 · ~1 min

Open/Closed Principle

Open for extension, closed for modification. New behavior should be addable without editing code that already works and is already tested — usually achieved through an abstraction (an interface or base class) that new behavior plugs into, rather than a growing conditional inside existing code.

// Violates OCP — every new discount type means editing this method,
// re-testing all the existing cases, and risking a regression in code
// that had nothing to do with the new discount type being added.
public decimal CalculateDiscount(Order order, string discountType)
{
    if (discountType == "percentage") return order.Total * 0.10m;
    if (discountType == "flat") return 10m;
    if (discountType == "loyalty") return order.Total * 0.05m + 5m;
    // every future discount type adds another branch here
    return 0m;
}
// Open for extension: adding VipDiscount means adding a new class,
// not touching CalculateDiscount or any existing discount class.
public interface IDiscount
{
    decimal Apply(Order order);
}

public class PercentageDiscount : IDiscount
{
    public decimal Apply(Order order) => order.Total * 0.10m;
}

public class FlatDiscount : IDiscount
{
    public decimal Apply(Order order) => 10m;
}

public class OrderProcessor
{
    public decimal CalculateDiscount(Order order, IDiscount discount) => discount.Apply(order);
}

This is the Strategy pattern (covered in full later in this reference) showing up as the standard mechanism for satisfying Open/Closed — the principle names the goal, Strategy is one concrete shape that achieves it. It's worth being honest about the trade-off: designing for extension you don't yet need is speculative complexity. OCP is most valuable exactly where a codebase's history shows a particular kind of change (new discount types, new payment providers, new export formats) keeps happening — not applied preemptively to every class on day one.