Robert C. Martin's first principle: every class should be responsible for a single part of the program's functionality, and that responsibility should be entirely encapsulated within it. If a class has more than one reason to change, it violates SRP.
Watch it separate
The central sphere carries five unrelated responsibilities. Press Split to break them into focused units.
drag — scroll to zoom
Code example
The same problem in C# and JavaScript. Toggle to compare.
SRP VIOLATION ? FIX
// ? BAD — UserService has three reasons to change
public class UserService
{
private readonly DbContext _db;
private readonly SmtpClient _smtp;
private readonly PdfWriter _pdf;
public void Register(User user)
{
_db.Users.Add(user); // ? persistence concern
_db.SaveChanges();
_smtp.Send("welcome@app.com", user.Email, "Welcome!"); // ? email concern
_pdf.Generate(user, "report.pdf"); // ? reporting concern
}
}
// ? GOOD — one class, one responsibility
public class UserRepository
{
public void Save(User u) { _db.Users.Add(u); _db.SaveChanges(); }
}
public class EmailService
{
public void SendWelcome(User u) { _smtp.Send("welcome@app.com", u.Email, "Welcome!"); }
}
public class ReportGenerator
{
public void Generate(User u) { _pdf.Generate(u, "report.pdf"); }
}
public class UserService // now only orchestrates
{
public void Register(User user)
{
_repo.Save(user);
_email.SendWelcome(user);
_report.Generate(user);
}
}
// ? BAD — one class, too many jobs
class UserService {
register(user) {
db.save(user); // persistence
mailer.send(user.email, // email
'Welcome!');
pdf.generate(user); // reporting
}
}
// ? GOOD — each class owns one concern
class UserRepository {
save(user) { db.save(user); }
}
class EmailService {
sendWelcome(user) { mailer.send(user.email, 'Welcome!'); }
}
class ReportGenerator {
generate(user) { pdf.create(user); }
}
class UserService {
constructor(repo, email, report) {
this.repo = repo;
this.email = email;
this.report = report;
}
register(user) {
this.repo.save(user);
this.email.sendWelcome(user);
this.report.generate(user);
}
}
Key concepts
🎯
Single Responsibility
one class — one job
Each class encapsulates exactly one behaviour. Changes to one area don't ripple into unrelated code.
🔄
One Reason to Change
cohesion — stability
If two stakeholders can independently ask for changes to the same class, it has two responsibilities.
🧩
High Cohesion
related — grouped
Everything inside a class belongs together. High cohesion makes code easier to read, test, and reuse.
⚠
The God Class
anti-pattern — avoid
A class that knows too much and does too much. Hard to test, impossible to reuse. SRP is the cure.