Solid Principle
SOLID Principle
What are the SOLID principles?
Five object-oriented design principles help make code:
-
Maintainable (easy to change without breaking things)
-
Extensible (easy to add new features)
-
Testable (easy to write unit tests)
-
Understandable (easy for other developers to read)
The five principles:
-
S – Single Responsibility Principle (SRP)
One class = one reason to change. -
O – Open/Closed Principle (OCP)
Open for extension, closed for modification. -
L – Liskov Substitution Principle (LSP)
Subclasses should work wherever base classes work (no broken contracts). -
I – Interface Segregation Principle (ISP)
Clients should not be forced to depend on methods they don’t use. -
D – Dependency Inversion Principle (DIP)
Depend on abstractions, not concrete classes.
Why are we using SOLID principles?
-
Reduce bugs when requirements change
→ You can modify code without breaking unrelated parts. -
Improve maintainability
→ Code is easier to understand and update. -
Encourage modular and reusable code
→ You can plug in new features instead of rewriting core logic. -
Improve testability
→ Smaller, decoupled classes are easier to test with unit tests and mocks. -
Team collaboration becomes easier
→ Different developers can work on different parts without conflicts.
What if we do NOT use SOLID principles?
-
Tight coupling → A small change in one place breaks many other places.
-
Code rigidity → Adding new features requires rewriting existing code.
-
Code fragility → Fixing one bug may create new bugs elsewhere.
-
Difficult testing → Large classes are hard to test in isolation.
-
Poor readability → New developers struggle to understand the codebase.
-
Slower delivery → Every change becomes risky and time-consuming.
Simple real-world analogy
Think of building a car:
-
With SOLID: Each part (engine, wheels, seats) has a clear purpose and can be replaced/upgraded without redesigning the whole car.
-
Without SOLID: Everything is welded together — changing the seat requires rebuilding the engine compartment.
Quick interview-style summary😜
We use SOLID to make code maintainable, extensible, and testable. Without it, our code becomes tightly coupled, hard to modify, full of bugs, and difficult to scale.
1. Single Responsibility Principle (SRP): A class (or module) should have only one reason to change.
(only one responsibility or job)
Why is SRP important?
-
Easier to understand – The class does only one thing, so its purpose is clear.
-
Easier to maintain – If a requirement changes, you only modify one class.
-
Easier to test – Focused classes are simpler to test in isolation.
-
Avoids ripple effects – Changes in one area won't unintentionally break another.
Example:
public class SingleResponsibility
{
public string SendEmail(string message)
{
return "Send Email";
}
}
Note: Only responsible for sending email.
***********************************************************************************
2. Open/Closed Principle (OCP): A class should be open for extension but closed for modification.
Why is OCP important?
Imagine a USB port on your computer:
-
The port design (interface) is fixed — you don’t modify the laptop every time a new device is invented.
-
You just plug in a new USB device — that's an extension without modification.
If the port design changed every time, you'd have to open the laptop and rewire things — not practical and very error-prone. Software behaves the same way.
Example:
public interface INotification
{
void Send(string message);
}
public class EmailNotification : INotification
{
public void Send(string message)
{
Console.WriteLine("Sending Email: " + message);
}
}
public class SMSNotification : INotification
{
public void Send(string message)
{
Console.WriteLine("Sending SMS: " + message);
}
}
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3.LSP (Liskov Substitution Principle) is the L in SOLID principles, introduced by Barbara Liskov.
In short:
LSP says, “If something works for a parent, it should also work for every child—no excuses, no surprises.”
Example in real life
Imagine you have a remote control that works for any TV.
-
The parent class = "Any TV"
-
The child classes = "Sony TV", "Samsung TV", "LG TV"
If you pick any TV (Sony, Samsung, LG) and the remote still works as expected, this follows LSP.
But what if one TV brand suddenly doesn’t respond to the volume button or turns off when you press mute?
-
That TV breaks the principle because it cannot be substituted without problems.
What happens if we don’t follow LSP?
-
Unexpected behaviour – things stop working when you switch classes.
-
Extra testing and patches – you must add special checks everywhere (e.g., "if Sony TV then do this… if Samsung TV do that…").
-
Hard to maintain – small changes can break other parts of the system.
Example:
// Parent class
public class Bird
{
public virtual void Fly()
{
Console.WriteLine("This bird can fly.");
}
}
// Child class 1
public class Sparrow : Bird
{
public override void Fly()
{
Console.WriteLine("Sparrow is flying.");
}
}
// Child class 2 (but doesn't really fly)
public class Penguin : Bird
{
public override void Fly()
{
throw new NotImplementedException("Penguins can't fly!");
}
}
4. Interface Segregation Principle (ISP): Clients should not be forced to depend on methods they do not use.
In other words:
-
Instead of one big “fat” interface with many methods,
-
Create smaller, specific interfaces so classes implement only what they need.
Why is ISP important?
-
Prevents bloated classes — Classes aren’t forced to implement irrelevant methods.
-
Reduces side effects — Changing an unused method in a large interface won’t accidentally affect classes that don't care about it.
-
Improves readability and maintainability — Interfaces describe one clear responsibility.
Real-world analogy
Think of TV remotes:
-
A single remote with 50 buttons (one giant interface) is confusing — even if you use only 3 buttons, you still have to carry all 50.
-
A small remote with just power, volume, and channel (segregated interface) is simpler and fits the purpose.
Step 1 – What is DIP in super easy words?
-
Normally, a big boss (parent) controls employees (child) directly.
-
If the boss changes how he works, employees get confused.
-
DIP says: Instead of boss controlling employees directly, both boss and employees should follow a common rulebook (interface).
-
This way, if either changes, the other one is not affected — because they just follow the same rulebook.
Step 2 – Simple real-life example
-
Bad way (no DIP):
AManager
class directly creates and uses aDeveloper
class. If you hire a Tester instead of a Developer, you must modify theManager
code. -
Good way (with DIP):
Manager
talks to anIEmployee
interface. BothDeveloper
andTester
implement this interface.
Now you can hire anyone, and the Manager doesn't change — he just follows the interface rulebook.
Step 3 – C# Example without DIP (Bad)
Problem: If you want to replace Developer with Tester, you must edit Manager code.
Step 4 – C# Example with DIP (Good)
Step 5 – Who is Parent and Child here?
-
Parent:
Manager
(the boss) -
Children:
Developer
,Tester
(employees) -
Middle Rulebook:
IEmployee
(interface) -
The manager doesn't care who is working — both just follow the interface.
Comments
Post a Comment