The SOLID principles are a set of guidelines that help developers design robust, maintainable, and scalable software systems. Introduced by Robert C. Martin, these principles are fundamental to object-oriented programming. Let’s explore each principle in detail:
A class should have one, and only one, reason to change. This means a class should only have one job or responsibility.
class Invoice { void calculateTotal() { // Calculation logic } void printInvoice() { // Printing logic } } // This violates SRP. The printing responsibility should be in another class.
Software entities (classes, modules, functions) should be open for extension but closed for modification.
interface Shape { double area(); } class Circle implements Shape { double area() { // Calculate area of circle } } class Rectangle implements Shape { double area() { // Calculate area of rectangle } } // New shapes can be added without modifying existing code.
Objects of a superclass should be replaceable with objects of a subclass without affecting the correctness of the program.
class Bird { void fly() { // Flying logic } } class Penguin extends Bird { void fly() { throw new UnsupportedOperationException(); } } // This violates LSP. Penguin is not substitutable for Bird.
Clients should not be forced to depend on interfaces they do not use.
interface Animal { void eat(); void fly(); // Violates ISP, as not all animals can fly. } interface Eatable { void eat(); } interface Flyable { void fly(); } // Segregating interfaces resolves the issue.
High-level modules should not depend on low-level modules. Both should depend on abstractions. Abstractions should not depend on details; details should depend on abstractions.
interface Database { void save(String data); } class MySQLDatabase implements Database { void save(String data) { // Save to MySQL } } class Application { Database database; void storeData(String data) { database.save(data); } } // Application depends on abstraction, not implementation.