Need to Extend, Not Rewrite: Why OCP Saves Your Sanity
- Maryanne
- Apr 10
- 2 min read
Updated: May 4
Ever added a new feature and accidentally broke the thing that was already working? Yeah, me too. That's what happens when our code isn't built to grow.
What Is the Open/Closed Principle?
"Software entities should be open for extension, but closed for modification." — Bertrand Meyer
Open to extension → Add new features without changing existing code.
Closed to modification → Don't touch old code that already works.
Why it matters:
Reduces risk of regressions
Makes code more testable and maintainable
Encourages clean separation of concerns
"Think of your code like a power strip. You don’t open it up every time you want to plug in a new device you just use the extra outlets. OCP is the same: design your code so you can add new behaviors without modifying the core."
The Anti-Example: Code That Violates OCP
public class NotificationService
{
public void Send(string message, string type)
{
if (type.Equals("email"))
{
// send email
}
else if (type.Equals("sms"))
{
// send SMS
}
}
}
What’s wrong?
Every time a new type is added (Slack, Teams, Push), the class needs to be edited.
This violates Open/Closed.
It breaks encapsulation and risks bugs.
The Fix: Open for Extension, Closed for Modification
Step 1: Use an interface to abstract the behavior
public interface INotifier
{
void Send(string message);
}
Step 2: Create extensible implementations
public class EmailNotifier : INotifier
{
public void Send(string message)
{
// Send email logic
}
}
public class SmsNotifier : INotifier
{
public void Send(string message)
{
// Send SMS logic
}
}
Step 3: Inject behavior into the service
public class NotificationService
{
private readonly INotifier notifier;
public NotificationService(INotifier notifier)
{
this.notifier = notifier;
}
public void Notify(string message)
{
notifier.Send(message);
}
}
Now want to add Slack? Just make a new SlackNotifier class no changes to NotificationService needed.
Boom. 🎤 Drop.
Real-World Use Cases
Payment processors (Stripe, PayPal, etc.)
Shipping methods
Authentication strategies
Game AI behaviors
Logging providers
Common Pitfalls
Overengineering: Don’t abstract everything. Only apply OCP when it solves a real problem.
Forgetting to use dependency injection.
Tightly coupling your "extension" logic.
Key Takeaways
OCP helps your code scale without becoming spaghetti.
Use interfaces or base classes to allow extension.
Keep your core logic stable and isolated.
Think plugins, not patches.
“Code is like Lego. If you have to glue the bricks to make them stick, you’re doing it wrong.”

Want to share one of your Bad Blocks? Would love to hear about it
Comentarios