DEV Community

Gabrielle Eduarda
Gabrielle Eduarda

Posted on

Open/Closed Principle: How to Write Code That Grows Without Breaking

If every new feature forces you to change what already works… something’s wrong.”

Have you ever opened a service and added just one more if?
Then another.
Then a switch-case.
Then prayed nothing else would break?

At first, it feels harmless — just one more condition.
But soon, you're wading through a sea of rules, dependencies, and fragile logic.

This is exactly what the Open/Closed Principle (OCP) — the "O" in SOLID — helps you avoid.

What is the OCP?
A module should be open for extension, but closed for modification.

In practice, it means you should be able to add new behavior without changing existing code.

It’s not just about clean code. It’s about safety, scalability, and long-term maintenance.

The less you change working code, the less you risk breaking it.

The problem with “if-chains”
Take this common example in a payment service:

public double CalculateFee(string paymentType) {
if (paymentType == "PIX") return 0;
if (paymentType == "BOLETO") return 3.5;
if (paymentType == "CARD") return 5.0;
return 0;
}
Now, your team needs to add Apple Pay, crypto, gift cards...

Each new method requires changing the original method — and hoping you don’t break what’s already there.

This clearly violates OCP — you’re modifying a core function instead of extending the system safely.

Applying OCP in .NET
Here’s how to do it right: use interfaces and polymorphism to extend behavior without modifying what's already written.

public interface IPayment {
double CalculateFee();
}

public class Pix : IPayment {
public double CalculateFee() => 0;
}

public class Boleto : IPayment {
public double CalculateFee() => 3.5;
}

public class Card : IPayment {
public double CalculateFee() => 5.0;
}
And instead of using conditionals, delegate behavior:

public class PaymentService {
public double GetFee(IPayment payment) {
return payment.CalculateFee();
}
}

Want to add Apple Pay?
Just create a new class.
No need to touch any existing logic.

That's the power of OCP — change through extension, not modification.

Real benefits of applying OCP
✔ Add features without touching stable code
✔ Easier unit testing and dependency injection
✔ Fewer bugs, regressions, and headaches
✔ Code that's easier to onboard and extend over time

When not to apply OCP?
Like any principle, OCP is not a hammer for every nail.

Practical tip:

Apply OCP when you expect varying behavior (payment types, notifications, report generation).

Avoid overengineering in simple, stable domains.

Final thoughts: OCP protects your code from the future
Every system grows.
But not all code is built to handle that growth.

The Open/Closed Principle gives your code a way to evolve without fear, keeping your foundation stable while adding value on top.

Top comments (0)