Back to Notes

SOLID Principles

The Five Principles

PrincipleOne lineExample
S — Single ResponsibilityOne class, one reason to changeOrderProcessor doesn't also send emails — that's a NotificationService's job
O — Open/ClosedOpen for extension, closed for modificationAdd StripeProcessor as a new subclass without editing PaymentProcessor
L — Liskov SubstitutionA subclass must be usable anywhere its base type is expected, without surprisesSquare should work correctly wherever Rectangle is used — if forcing width == height breaks callers that resize independently, it violates LSP
I — Interface SegregationDon't force classes to implement methods they don't needSplit one fat interface into several focused ones (Readable, Writable) rather than one Storage interface with both
D — Dependency InversionDepend on abstractions, not concrete implementationsInject a PaymentProcessor interface into a class, not a concrete StripeProcessor

Why These Matter Beyond Being Vocabulary

Interviewers use SOLID violations as a live signal during the implementation phase, not just a definitions quiz. A design that hardcodes if vehicle_type == "car" branching all over instead of polymorphic dispatch is an Open/Closed violation happening in real time — naming it while you're coding, and refactoring toward it, is a stronger signal than reciting the definitions upfront and then not applying them.

The One Genuinely Tricky One: Liskov Substitution

The classic square/rectangle example is subtle because it looks like valid inheritance (a square is-a rectangle geometrically) but breaks behaviorally:

class Rectangle:
    def __init__(self, w, h): self.w, self.h = w, h
    def set_width(self, w): self.w = w
    def area(self): return self.w * self.h

class Square(Rectangle):
    def set_width(self, w):
        self.w = self.h = w   # forces height to match — surprises any caller
                               # that expected set_width to leave height alone

Any code that does rect.set_width(5); assert rect.area() == 5 * original_height breaks silently when handed a Square. The fix isn't a cleverer inheritance hierarchy — it's recognizing Square and Rectangle shouldn't be in an is-a relationship for a mutable shape API at all. This is the kind of follow-up that separates candidates who memorized SOLID from candidates who understand why it exists.

Interview Drill

Q: A NotificationService class has methods send_email(), send_sms(), and log_delivery_metrics(). Which principle does this violate, and how do you fix it? A: Single Responsibility — sending notifications and logging metrics are two different reasons to change (a new notification channel vs a new metrics backend). Split into NotificationService and a separate DeliveryMetricsLogger, composed together rather than merged into one class.

Cross-links

[[LLD Interview Approach]] · [[OOD Design Patterns]]