SOLID Principles
The Five Principles
| Principle | One line | Example |
|---|---|---|
| S — Single Responsibility | One class, one reason to change | OrderProcessor doesn't also send emails — that's a NotificationService's job |
| O — Open/Closed | Open for extension, closed for modification | Add StripeProcessor as a new subclass without editing PaymentProcessor |
| L — Liskov Substitution | A subclass must be usable anywhere its base type is expected, without surprises | Square should work correctly wherever Rectangle is used — if forcing width == height breaks callers that resize independently, it violates LSP |
| I — Interface Segregation | Don't force classes to implement methods they don't need | Split one fat interface into several focused ones (Readable, Writable) rather than one Storage interface with both |
| D — Dependency Inversion | Depend on abstractions, not concrete implementations | Inject 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]]