In the previous article, we discussed why Object-Oriented Programming alone wasn't enough and how the SOLID principles emerged to help developers design more maintainable software.
Today, we'll explore the first principle:
Single Responsibility Principle (SRP).
Many developers hear:
A class should have only one responsibility.
Then immediately wonder:
Does that mean a class should have only one method?
Or:
Should every class do just one tiny thing?
Not quite.
Let's understand the problem SRP was trying to solve.
The Problem
Imagine we're building an e-commerce application.
We create an OrderService.
Initially, its job is simple.
OrderService
✓ Create Order
Everything looks fine.
As the application grows, new requirements arrive.
"We need to calculate discounts."
No problem.
OrderService
✓ Create Order
✓ Calculate Discount
A week later:
"We should send a confirmation email."
OrderService
✓ Create Order
✓ Calculate Discount
✓ Send Email
A month later:
"We also need to generate invoices."
OrderService
✓ Create Order
✓ Calculate Discount
✓ Send Email
✓ Generate Invoice
Then someone asks for audit logs.
Inventory updates.
Loyalty points.
Analytics.
Before long, the class looks like this:
OrderService
✓ Create Order
✓ Calculate Discount
✓ Process Payment
✓ Update Inventory
✓ Generate Invoice
✓ Send Email
✓ Record Analytics
✓ Write Audit Logs
The application still works.
But something feels wrong.
What's the Real Problem?
The issue isn't the number of methods.
The issue is that the class is trying to solve too many different problems.
Think about who might request changes.
The finance team may ask for invoice changes.
The marketing team may introduce a new discount strategy.
Operations may change inventory rules.
Customer support may request a different email template.
Analytics may require new tracking events.
Every team has a different reason to modify the same class.
Now imagine multiple developers working on it simultaneously.
Merge conflicts become common.
Testing becomes more difficult.
A small change in one area can accidentally affect another.
The class has become a bottleneck.
The Idea Behind SRP
This is where the Single Responsibility Principle comes in.
It says:
A class should have one, and only one, reason to change.
Notice something important.
It doesn't say:
One method.
It doesn't say:
One line of code.
It says:
One reason to change.
A responsibility isn't defined by the amount of code.
It's defined by the purpose the class serves.
Breaking Responsibilities Apart
Instead of putting everything into one class, we separate concerns.
OrderService
│
├── DiscountService
├── PaymentService
├── InventoryService
├── EmailService
├── InvoiceService
└── AnalyticsService
Now each class has a clear responsibility.
If invoice generation changes, we modify InvoiceService.
If email templates change, we modify EmailService.
If discount rules change, we modify DiscountService.
Each class evolves independently.
Another Real-World Example
Think about a restaurant.
One person could:
Take orders.
Cook food.
Wash dishes.
Manage inventory.
Handle payments.
Clean tables.
Technically, it's possible.
But would it be efficient?
Probably not.
Restaurants divide responsibilities because specialization makes the system easier to manage.
Software is no different.
What SRP Doesn't Mean
SRP is often misunderstood.
It doesn't mean:
❌ Every class should contain only one method.
❌ Every file should be tiny.
❌ Every function deserves its own class.
Those interpretations usually lead to unnecessary complexity.
Instead, ask yourself:
Does this class represent one clear responsibility?
If the answer is yes, you're likely on the right track.
Benefits of SRP
Following SRP makes software easier to:
- Understand
- Test
- Maintain
- Extend
It also reduces the chances that unrelated changes will accidentally affect each other.
Are There Trade-offs?
Absolutely.
Like every design principle, SRP can be overused.
If every tiny operation becomes its own class, you'll end up with hundreds of small classes that are difficult to navigate.
Good software design is about balance.
Split responsibilities when they truly represent different reasons to change.
Don't split code simply because you can.
What's Next?
We've learned how to design classes with focused responsibilities.
But another challenge still remains.
What happens when a new feature requires changing an existing, well-tested class?
Should we keep modifying it?
Or is there a better way?
In the next article, we'll explore the Open/Closed Principle (OCP) and learn why software should be open for extension but closed for modification.

Top comments (0)