The Open/Closed Principle (OCP) is the “O” in SOLID, and a critical principle for designing flexible, scalable, and future-proof systems. In this article, we will cover OCP from basic theory to advanced practical applications across backend systems, frontend interfaces, testing strategies, and real-world architecture.
π‘ What is the Open/Closed Principle (OCP)?
βSoftware entities (classes, modules, functions) should be open for extension but closed for modification.β β Bertrand Meyer
This means we should be able to add new behavior to our systems without modifying existing tested code.
β
Extend = Add new code.
β
Closed = Do not touch old working code.
π¬ Visual Metaphor: Smart City Transport
You have a smart city controlling cars and buses. Tomorrow, drones need to be integrated.
β
If you designed transport rules via interfaces, you can plug in drones easily.
β If rules are hardcoded for only cars and buses, you must rewrite logic = risk of bugs.
π¨ Code-Level Application: Replacing Switches with Strategies
β Violation:
if (paymentType.equals("UPI")) handleUPI();
else if (paymentType.equals("CARD")) handleCard();
β OCP Fix (Strategy Pattern):
interface PaymentStrategy { String getType(); void pay(); }
class UpiPayment implements PaymentStrategy { ... }
class CardPayment implements PaymentStrategy { ... }
Inject via Spring Boot:
Map<String, PaymentStrategy> strategies;
strategies.get(type).pay();
No switch-case modification. Just new strategies plugged in.
βοΈ OCP in Spring Boot
Interface:
public interface NotificationChannel {
String getType();
void send(Message msg);
}
Components:
@Component
public class EmailChannel implements NotificationChannel { ... }
Service Injection:
@Autowired
public NotificationService(List<NotificationChannel> channels) {
for (var c : channels) map.put(c.getType(), c);
}
β New channels auto-discovered without modifying existing NotificationService.
π§ͺ Testing OCP-Compliant Code
- Strategies tested independently.
- Core service doesnβt require modification/testing if new behavior is added.
@Test void testEmailChannel() { emailChannel.send(message); }
@Test void testServiceDelegation() { notificationService.send("email", message); }
π§© Real-World Violations and Their OCP Fixes
| Violation | Fix |
|---|---|
switch(user.role) | RoleHandler strategy map |
if (reportType == ...) | ReportGenerator strategy interface |
| Feature flags inside business logic | FeatureStrategy plugins |
| DTO mapping with instanceof chains | Formatter pattern |
π OCP in Frontend (React/Angular)
| Feature | OCP Strategy |
|---|---|
| Dynamic Forms | Schema-driven FieldType β Component Map |
| Theme Switching | Abstract tokens with ThemeProvider |
| Dashboard Widgets | Type β Component plugin map |
const FieldTypeMap = {
text: TextInput,
select: SelectBox,
date: DatePicker,
};
β Add new field types without modifying core form renderer.
π OCP in API Layer (Spring Boot)
| API Use Case | OCP Strategy |
|---|---|
| API Versioning | VersionHandler strategy map |
| Content Negotiation | ContentSerializer per format |
| Field Projection (GraphQL) | Transformer per DTO/field set |
| Export Files (PDF/CSV) | Exporter strategy loader |
interface ContentSerializer {
boolean supports(String type);
String serialize(Object obj);
}
β Adding new formats/extensions without touching controllers.
β οΈ Drawbacks and Overuse of OCP
| Symptom | Risk |
|---|---|
| Too many tiny classes | Class explosion |
| Premature abstraction | Added complexity with no real need |
| Debugging difficulty | Traceability issues |
| Interface fatigue | Abstracting non-volatile parts unnecessarily |
β Tip: Only apply OCP when volatility is observed or anticipated realistically.
β Summary: Ways to Apply OCP
π In Code
- Interfaces + Polymorphism
- Strategy Pattern, Command Pattern
- Spring Bootβs
List<Interface>injection - Handler maps for resolution
π In API
- API version handlers
- Content serializers
- DTO transformers
- Exporter strategies
π» In Frontend
- Schema-driven form renderers
- Theming providers
- Widget/plugin component maps
β Apply OCP mindfully, not mindlessly.
π Final Reflection
The Open/Closed Principle helps you:
- Roll out new features faster
- Maintain stable tested bases
- Empower plugins, modules, extensions
- Reduce regression risk dramatically
Good software grows by extension, not mutation.
Leave a comment