# SOLID Principles
## Summary
SOLID is a set of five fundamental principles for object-oriented software design introduced by Robert C. Martin in 2000. These principles help create more maintainable, flexible, and scalable software systems. Each letter in SOLID represents a specific principle that addresses common software design challenges and promotes best practices in code organisation.
Key benefits:
- Reduces dependencies between components
- Makes code easier to maintain and modify
- Supports better testing practices
- Enhances code reusability
- Promotes cleaner architecture
## Details
### Single Responsibility Principle (SRP)
A class should have one, and only one, reason to change. This means each class should focus on a single responsibility or concern.
Benefits:
- Simpler testing with fewer test cases
- Lower coupling between components
- Better code organisation
- Easier maintenance
Example:
Instead of having a Book class that handles both book properties and printing:
```java
// Good: Separate classes for different responsibilities
public class Book {
private String name;
private String author;
private String text;
public String replaceWordInText(String word, String replacement) {
return text.replaceAll(word, replacement);
}
}
public class BookPrinter {
void printTextToConsole(String text) {
// Printing logic
}
void printTextToAnotherMedium(String text) {
// Other output logic
}
}
```
### Open-Closed Principle (OCP)
Software entities should be open for extension but closed for modification. This encourages adding new functionality through new code rather than changing existing code.
Benefits:
- Reduces risk of bugs in existing code
- Maintains backward compatibility
- Promotes code reuse
- Supports incremental development
Example:
```java
public class Guitar {
private String make;
private String model;
private int volume;
// Base functionality
}
public class SuperCoolGuitarWithFlames extends Guitar {
private String flameColor;
// Extended functionality without modifying original
}
```
### Liskov Substitution Principle (LSP)
Subtypes must be substitutable for their base types without altering the correctness of the program. This ensures that inheritance is used correctly.
Benefits:
- Maintains consistent behavior
- Ensures proper inheritance hierarchies
- Prevents unexpected side effects
- Supports code reusability
Example:
```java
public interface Car {
void accelerate();
void brake();
}
public class ElectricCar implements Car {
public void accelerate() {
// Electric acceleration
}
public void brake() {
// Electric braking with regeneration
}
}
public class PetrolCar implements Car {
public void accelerate() {
// Petrol engine acceleration
}
public void brake() {
// Traditional braking
}
}
```
### Interface Segregation Principle (ISP)
Clients should not be forced to depend on interfaces they don't use. This promotes creating focused, specific interfaces rather than large, general-purpose ones.
Benefits:
- Reduces code coupling
- Improves maintainability
- Makes interfaces more focused
- Prevents unnecessary implementation
Example:
```java
// Instead of one large interface:
public interface BearKeeper {
void washTheBear();
void feedTheBear();
void petTheBear();
}
// Break into specific interfaces:
public interface BearCleaner {
void washTheBear();
}
public interface BearFeeder {
void feedTheBear();
}
```
### Dependency Inversion Principle (DIP)
High-level modules should not depend on low-level modules. Both should depend on abstractions. This principle promotes loose coupling through dependency injection and interface-based design.
Benefits:
- Enables better testing
- Supports modularity
- Facilitates change
- Promotes reusability
Example:
```java
// Instead of:
public class Windows98Machine {
private final StandardKeyboard keyboard;
private final Monitor monitor;
public Windows98Machine() {
keyboard = new StandardKeyboard();
monitor = new Monitor();
}
}
// Better approach:
public interface Keyboard {}
public interface Monitor {}
public class Windows98Machine {
private final Keyboard keyboard;
private final Monitor monitor;
public Windows98Machine(Keyboard keyboard, Monitor monitor) {
this.keyboard = keyboard;
this.monitor = monitor;
}
}
```
## 🔗 Related Resources
- [[Clean Code]] - Principles for writing maintainable code
- [[Design Patterns]] - Common software design patterns
- [[Object Oriented Design]] - Fundamentals of OOP design