SOLID principles
intermediateOpen/Closed Principle (OCP)
Software entities should be open for extension, but closed for modification.
You should be able to add new behaviour without editing code that already works. That is OCP: open to adding, closed to editing.
A power outlet is closed for modification — you don't rewire the wall to use a new appliance. But it's open for extension — any device with the right plug works.
Key Concepts
1
Why editing working code is a risk. Every time you open a file that already works and change it, you
might break something that was fine yesterday. Adding a new file cannot break the old ones.
2
An example. You calculate a fee, and the fee depends on the payment method:
3
switch (payment.type()) {
case CARD: return amount * 0.02;
case UPI: return 0;
case NETBANKING: return 10;
}4
Now add a new payment method. You edit this file. Then you find the same switch in the validator, and
another in the report. Miss one and you get a bug that nobody notices for weeks.
switch
5
The fix is one class per type. Define an interface, PaymentMethod, with a fee() method. Each
payment type becomes its own small class. Adding a method means adding a file. Nothing existing is
touched, so nothing existing can break.
PaymentMethodfee()
6
The signal to watch for is repetition. One switch on a type is fine. The same switch appearing
in three places is the signal — that is when the interface pays for itself.
switch
7
Do not do this too early. Building an extension point before you have a second case means guessing
what the second case will look like. You usually guess wrong, and the real second case does not fit.
Write the simple version first. Refactor when the second case arrives and you can see its shape.
8
Sometimes you want the opposite. If the set of types is fixed and will not grow — a payment status is
Pending, Settled or Failed, and that is all there is — use a sealed interface and a switch. The
compiler then checks every switch for you and fails the build if someone adds a fourth. That is more
useful than an open interface when the list is genuinely closed.
PendingSettledFailed
9
What the interviewer is probing.1. "What does OCP mean?" Probing: the idea plus how you would do it. Stalls: repeating the phrase.
Moves up: add behaviour in new classes rather than editing old ones, done with an interface.
10
2. "Show me a violation." Probing: whether you recognise it in code. Stalls: a vague answer.
Moves up: the same type switch repeated in several files, where adding a type means finding them all.
switch
11
3. "When would you not do this?" Probing: judgement. Stalls: "Always do it." Moves up: before a
second case exists, because the extension point is built on a guess.
12
4. "What about sealed interfaces?" Probing: whether you know the newer option. Stalls: "They are
new." Moves up: when the list of types is closed, a sealed interface plus a switch makes the compiler
find every place that needs updating.
13
5. "Does fixing a bug break the rule?" Probing: whether you treat it as dogma. Stalls: "Yes."
Moves up: no. The rule is about adding new behaviour, not about never touching code.
14
Violation: the switch that keeps growing15
BigDecimal fee(Payment p) {
switch (p.type()) {
case CARD: return p.amount().multiply(0.02);
case UPI: return ZERO;
case NETBANKING: return TEN;
// every new method edits this, and the validator,
// and the reporter...
}
}16
Open for extension17
interface PaymentMethod {
BigDecimal fee(BigDecimal amount);
boolean supports(PaymentType type);
}
// a new method is a new class; nothing existing is edited18
Closed variant set: prefer sealed + exhaustive switch19
sealed interface Status permits Pending, Settled, Failed {}20
String describe(Status s) {
return switch (s) { // no default needed
case Pending p -> "waiting";
case Settled x -> "done";
case Failed f -> "failed: " + f.reason();
};
}
// adding a variant breaks compilation at EVERY switch --
// which is exactly what you want when the set is closed21
Choosing
open, growing set (payment providers, exporters) -> interface
closed, known set (status, AST node, result type) -> sealed
one case today, no second in sight -> neither;
write it
simply