Section 1 of 5
SOLID Principles
🎯 What You'll Learn
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
What is SOLID?
SOLID is a set of five design principles that make software more maintainable, flexible, and scalable.
S - Single Responsibility Principle (SRP)
A class should have only one reason to change.
❌ Bad: Multiple Responsibilities
C#
public class OrderProcessor
{
public void ProcessOrder(Order order)
{
// Validate order
// Save to database
// Send email
// Generate invoice
}
}
✅ Good: Single Responsibility
C#
public class OrderValidator
{
public bool Validate(Order order) { }
}
public class OrderRepository
{
public void Save(Order order) { }
}
public class EmailService
{
public void SendOrderConfirmation(Order order) { }
}
public class InvoiceGenerator
{
public void Generate(Order order) { }
}
O - Open/Closed Principle (OCP)
Open for extension, closed for modification.
❌ Bad: Modifying Existing Code
C#
public class DiscountCalculator
{
public decimal Calculate(decimal price, string customerType)
{
if (customerType == "Regular")
return price * 0.95m;
else if (customerType == "Premium")
return price * 0.90m;
return price;
}
}
✅ Good: Extension via Abstraction
C#
public interface IDiscountStrategy
{
decimal Calculate(decimal price);
}
public class RegularDiscount : IDiscountStrategy
{
public decimal Calculate(decimal price) => price * 0.95m;
}
public class PremiumDiscount : IDiscountStrategy
{
public decimal Calculate(decimal price) => price * 0.90m;
}
L - Liskov Substitution Principle (LSP)
Subtypes must be substitutable for their base types.
❌ Bad: Violates LSP
C#
public class Rectangle
{
public virtual int Width { get; set; }
public virtual int Height { get; set; }
}
public class Square : Rectangle
{
public override int Width
{
set { base.Width = base.Height = value; }
}
}
✅ Good: Separate Abstractions
C#
public interface IShape
{
int GetArea();
}
public class Rectangle : IShape
{
public int Width { get; set; }
public int Height { get; set; }
public int GetArea() => Width * Height;
}
public class Square : IShape
{
public int Side { get; set; }
public int GetArea() => Side * Side;
}
I - Interface Segregation Principle (ISP)
Clients should not depend on interfaces they don't use.
❌ Bad: Fat Interface
C#
public interface IProduct
{
void Add();
void Update();
void Delete();
void Print();
void Export();
}
✅ Good: Segregated Interfaces
C#
public interface IProductRepository
{
void Add(Product product);
void Update(Product product);
void Delete(int id);
}
public interface IPrintable
{
void Print();
}
public interface IExportable
{
void Export();
}
D - Dependency Inversion Principle (DIP)
Depend on abstractions, not concretions.
❌ Bad: Depends on Concrete Class
C#
public class OrderService
{
private readonly SqlServerRepository _repository;
public OrderService()
{
_repository = new SqlServerRepository();
}
}
✅ Good: Depends on Abstraction
C#
public class OrderService
{
private readonly IOrderRepository _repository;
public OrderService(IOrderRepository repository)
{
_repository = repository;
}
}
Key Takeaways
- SRP: One class, one responsibility
- OCP: Extend behavior without modifying code
- LSP: Subtypes must be substitutable
- ISP: Small, focused interfaces
- DIP: Depend on abstractions, not implementations