100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Software Design

SOLID Principles Recap

A refresher on the five SOLID object-oriented design principles and how they form the underlying rationale for many Gang of Four design patterns.

FoundationsIntermediate10 min readJul 10, 2026
Analogies

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.

python
# 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

Was this page helpful?

Topics covered

#SoftwareDesign#DesignPatternsStudyNotes#SoftwareEngineering#SOLIDPrinciplesRecap#SOLID#Principles#Recap#Single#StudyNotes#SkillVeris