2 min read

SOLID Principles

SOLID is an acronym for five design principles intended to make software designs more understandable, flexible, and maintainable. They are a subset of many principles promoted by Robert C. Martin (Uncle Bob).

1. Single Responsibility Principle (SRP)

"A class should have one, and only one, reason to change."

This means a class should have only one job. If a class handles user authentication and sending emails, it violates SRP.

  • Bad: User class handles login, database saving, and email notifications.
  • Good: User class holds data. AuthService handles login. EmailService handles notifications.

2. Open/Closed Principle (OCP)

"Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification."

You should be able to add new functionality without changing existing code. This is often achieved using inheritance or interfaces.

  • Example: Instead of a calculateArea function with a big if/else for every shape, create a Shape interface with an area() method. To add a new shape, you just create a new class implementing Shape; you don't touch the existing calculation logic.

3. Liskov Substitution Principle (LSP)

"Subtypes must be substitutable for their base types."

If class B is a subclass of class A, you should be able to use an object of type B anywhere you use an object of type A without breaking the program.

  • Violation: A Square class inherits from Rectangle but changing the width also changes the height. If code expects a Rectangle where width and height are independent, passing a Square will cause bugs.

4. Interface Segregation Principle (ISP)

"Clients should not be forced to depend upon interfaces that they do not use."

It is better to have many specific interfaces than one general-purpose interface.

  • Bad: Worker interface has work() and eat(). A Robot class implements Worker but has to implement eat() (which it doesn't do).
  • Good: Split into Workable and Feedable. Robot only implements Workable.

5. Dependency Inversion Principle (DIP)

"Depend upon abstractions, [not] concretions."

High-level modules should not depend on low-level modules. Both should depend on abstractions (interfaces).

  • Bad: A Store class creates an instance of SQLDatabase inside its constructor. It is tightly coupled.
  • Good: Store accepts an argument of type Database (interface). You can pass in SQLDatabase, MongoDatabase, or MockDatabase for testing.

programming/object-oriented-programming programming/design-patterns programming/refactoring-techniques