SOLID Principles Recap
SOLID is an acronym for five object-oriented design principles popularized by Robert C. Martin ('Uncle Bob') that describe the qualities of maintainable, extensible code: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, and Dependency Inversion. These principles are not patterns themselves but the underlying rationale many design patterns exist to satisfy — for example, Strategy exists largely to satisfy Open/Closed, and Dependency Inversion is the theoretical basis for both the Factory patterns and dependency injection frameworks. Understanding SOLID makes it much easier to recognize why a given pattern is structured the way it is.
Cricket analogy: A team's overall game plan (batting deep, rotating bowlers, setting field placements) is the underlying philosophy that specific tactics like a nightwatchman or a leg-slip trap exist to serve, the way SOLID is the philosophy patterns exist to serve.
Single Responsibility and Open/Closed
The Single Responsibility Principle (SRP) states a class should have only one reason to change — mixing, say, order validation, tax calculation, and email receipt formatting into one OrderProcessor class means a tax-rate change and an email-template change both force edits to the same file, increasing risk with every deploy. The Open/Closed Principle (OCP) states software entities should be open for extension but closed for modification: rather than adding a new 'if' branch to an existing method every time a new payment type appears, you add a new class implementing a shared interface, leaving tested code untouched. This is precisely the problem Strategy and Template Method solve structurally.
Cricket analogy: A team that assigns one specialist wicketkeeper instead of asking a part-time gloveman to also open the batting keeps each role focused on a single responsibility, reducing the risk that a bad day at one job wrecks the other.
# Open/Closed via Strategy: extend without modifying existing code
class PaymentMethod:
def pay(self, amount: float) -> str:
raise NotImplementedError
class CreditCardPayment(PaymentMethod):
def pay(self, amount):
return f"Charged ${amount:.2f} to credit card"
class PayPalPayment(PaymentMethod):
def pay(self, amount):
return f"Sent ${amount:.2f} via PayPal"
# Adding CryptoPayment later requires zero changes to existing classes below:
class CryptoPayment(PaymentMethod):
def pay(self, amount):
return f"Transferred ${amount:.2f} in crypto"
def checkout(method: PaymentMethod, amount: float) -> str:
return method.pay(amount) # closed for modification, open for extension
Liskov Substitution, Interface Segregation, Dependency Inversion
The Liskov Substitution Principle (LSP) requires that subtypes be substitutable for their base types without breaking correctness — the classic violation is a Square subclassing Rectangle and overriding setWidth/setHeight in a way that breaks callers expecting independent width and height. The Interface Segregation Principle (ISP) says clients shouldn't be forced to depend on methods they don't use, favoring several small, focused interfaces over one large one. The Dependency Inversion Principle (DIP) states high-level modules shouldn't depend on low-level modules; both should depend on abstractions — this is the theoretical foundation of dependency injection and is what makes patterns like Factory Method, Abstract Factory, and Bridge possible.
Cricket analogy: Selecting a genuine all-rounder who can be substituted into either a specialist batting or bowling slot without the team plan breaking is Liskov Substitution in a squad, while a batting-only player forced to bowl would violate it.
A useful test for ISP: if implementing an interface forces you to write empty or 'throw NotSupportedException' method bodies, the interface is too fat and should be split into smaller, role-specific interfaces.
SOLID principles are guidelines, not laws to apply mechanically everywhere. Splitting every two-line class into five interfaces 'to be SOLID' produces the same over-engineering problem as applying patterns without a real need — apply each principle where it solves a real, present maintenance risk.
- SOLID = Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion.
- SOLID principles are the rationale behind many patterns, not patterns themselves.
- SRP: a class should have only one reason to change.
- OCP: entities should be open for extension, closed for modification — the basis for Strategy and Template Method.
- LSP: subtypes must be substitutable for their base type without breaking correctness.
- ISP: prefer several small, focused interfaces over one large, fat interface.
- DIP: depend on abstractions, not concrete low-level modules — the basis for dependency injection and Factory patterns.
Practice what you learned
1. What does the 'S' in SOLID stand for?
2. Which principle states software entities should be open for extension but closed for modification?
3. What does the Liskov Substitution Principle require?
4. What is a practical test for detecting an Interface Segregation Principle violation?
5. What is the Dependency Inversion Principle the theoretical basis for?
Was this page helpful?
You May Also Like
Why Design Patterns Matter
Why learning design patterns pays off: they compress collective engineering experience, create shared vocabulary that speeds up communication, and encode documented trade-offs that build judgment.
Choosing the Right Pattern
A practical framework for diagnosing the actual problem in your code first, then matching it to the smallest design pattern that resolves it, and avoiding common pattern-selection mistakes.
The Gang of Four and Pattern Categories
How the 1994 Gang of Four catalog organized 23 object-oriented design patterns into Creational, Structural, and Behavioral categories, with representative examples of each.
Related Reading
Related Study Notes in Software Engineering
Browse all study notesMicroservices Study Notes
Software Architecture · 30 topics
Software EngineeringTesting & TDD Study Notes
Software Testing · 30 topics
Software EngineeringSoftware Engineering Study Notes
Python · 40 topics
Software EngineeringGit & Version Control Study Notes
Bash · 40 topics
Software EngineeringSystem Design Study Notes
Architecture · 40 topics