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:
Userclass handles login, database saving, and email notifications. - Good:
Userclass holds data.AuthServicehandles login.EmailServicehandles 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
calculateAreafunction with a bigif/elsefor every shape, create aShapeinterface with anarea()method. To add a new shape, you just create a new class implementingShape; 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
Squareclass inherits fromRectanglebut changing the width also changes the height. If code expects aRectanglewhere width and height are independent, passing aSquarewill 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:
Workerinterface haswork()andeat(). ARobotclass implementsWorkerbut has to implementeat()(which it doesn't do). - Good: Split into
WorkableandFeedable.Robotonly implementsWorkable.
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
Storeclass creates an instance ofSQLDatabaseinside its constructor. It is tightly coupled. - Good:
Storeaccepts an argument of typeDatabase(interface). You can pass inSQLDatabase,MongoDatabase, orMockDatabasefor testing.
programming/object-oriented-programming programming/design-patterns programming/refactoring-techniques