| Users / Scale | System Behavior | Code Impact | Extension Needs |
|---|---|---|---|
| 100 users | Simple features, low traffic | Few classes, minimal changes | Rare new features, small fixes |
| 10,000 users | More features, moderate traffic | More classes, some refactoring | New features added often |
| 1,000,000 users | High traffic, complex features | Many modules, strict interfaces | Frequent extensions without breaking |
| 100,000,000 users | Massive scale, distributed system | Highly modular, plugin-based | Continuous extension, minimal downtime |
Open/Closed Principle in LLD - Scalability & System Analysis
When the system grows, the first bottleneck is the rigidity of code changes. Without following the Open/Closed Principle, adding new features requires modifying existing code. This leads to bugs and slows development.
At scale, this causes longer release cycles and higher risk of breaking existing functionality.
- Use abstraction: Define interfaces or abstract classes so new features extend without changing existing code.
- Modular design: Break system into independent modules that can be extended separately.
- Plugin architecture: Allow adding new functionality as plugins without touching core code.
- Automated testing: Ensure extensions do not break existing behavior.
- Code reviews and documentation: Maintain clear contracts for extensions.
Following Open/Closed Principle reduces development time and bug fixes as system scales.
For example, at 1,000,000 users, if each new feature requires modifying existing code, the risk of bugs grows linearly with features. This can cause delays of weeks per release.
By designing for extension, new features can be added in days, saving developer hours and reducing downtime.
When discussing scalability, explain how Open/Closed Principle helps manage complexity as features grow.
Structure your answer by:
- Describing the problem of changing existing code.
- Explaining how abstraction and modularity solve it.
- Giving examples of plugin or interface-based designs.
- Highlighting benefits like faster releases and fewer bugs.
Your system's database handles 1000 QPS. Traffic grows 10x and new features are requested frequently. What do you do first?
Answer: Apply the Open/Closed Principle by refactoring code to use abstractions and modular design. This allows adding new features without changing existing code, reducing risk and speeding development to handle increased demand.
Practice
Solution
Step 1: Understand the definition of OCP
The Open/Closed Principle states that software components should allow new functionality to be added without changing existing code.Step 2: Match the principle to the options
Software entities should be open for extension but closed for modification correctly states that entities should be open for extension (new features) but closed for modification (existing code remains unchanged).Final Answer:
Software entities should be open for extension but closed for modification. -> Option AQuick Check:
OCP = Open for extension, closed for modification [OK]
- Confusing 'open for extension' with 'open for modification'
- Thinking OCP means rewriting code for new features
- Ignoring the 'closed for modification' part
Solution
Step 1: Identify structures that allow extension without modification
Inheritance and interfaces allow new classes to add behavior without changing existing classes.Step 2: Evaluate options against OCP
Using inheritance or interfaces to add new behavior without changing existing code uses inheritance/interfaces, which aligns with OCP. Other options involve modifying or duplicating code, violating OCP.Final Answer:
Using inheritance or interfaces to add new behavior without changing existing code. -> Option AQuick Check:
Inheritance/interfaces = OCP support [OK]
- Thinking direct modification supports OCP
- Believing code duplication is acceptable
- Ignoring design patterns that enable extension
class Shape {
area() { return 0; }
}
class Rectangle extends Shape {
constructor(width, height) {
super();
this.width = width;
this.height = height;
}
area() { return this.width * this.height; }
}
class Circle extends Shape {
constructor(radius) {
super();
this.radius = radius;
}
area() { return Math.PI * this.radius * this.radius; }
}
function totalArea(shapes) {
return shapes.reduce((sum, shape) => sum + shape.area(), 0);
}What principle does this design demonstrate?
Solution
Step 1: Analyze how new shapes are added
New shape classes (Rectangle, Circle) extend Shape and implement area(). totalArea works without changes.Step 2: Match design to OCP
Since totalArea does not change when new shapes are added, the design follows Open/Closed Principle.Final Answer:
Open/Closed Principle by allowing new shapes without modifying totalArea. -> Option DQuick Check:
Adding shapes without changing totalArea = OCP [OK]
- Confusing OCP with other SOLID principles
- Thinking totalArea must change for new shapes
- Ignoring inheritance usage
class Report {
generate(type) {
if (type === 'pdf') {
// generate PDF
} else if (type === 'html') {
// generate HTML
}
}
}What is the best fix to comply with OCP?
Solution
Step 1: Identify why current code violates OCP
Adding new report types requires modifying generate() method, breaking OCP.Step 2: Choose design that allows extension without modification
Separate classes for each report type implementing a common interface allow adding new types without changing existing code.Final Answer:
Create separate classes for each report type implementing a common interface. -> Option BQuick Check:
Separate classes = extend without modify [OK]
- Adding more if-else blocks inside methods
- Ignoring interface or inheritance use
- Using global variables for behavior control
Solution
Step 1: Understand the requirement for extensibility without modification
The system must allow adding new payment methods without changing existing code.Step 2: Evaluate design options for OCP compliance
Implementing a Payment interface and creating new classes for each method allows extension by adding classes, not modifying existing ones.Final Answer:
Implement a Payment interface and create new classes for each payment method. -> Option CQuick Check:
Interface + new classes = OCP compliance [OK]
- Using switch statements that require modification
- Rewriting existing code repeatedly
- Using global flags for behavior control
Ready to prove it?
Pass the test and this pattern moves unknown
