Single responsibility principle states that every class or a module should have only one responsibility. Responsibility means a difference in usage scenario or a reason to change.
“There should never be more than one reason for a class to change”
Robert C. Martin
It is much better to have many small classes with distinct responsibilities than a big one. Do not be afraid that too many classes will affect readability. It is easier to find your stuff when it is organized in drawers than put all together in one big box!

Example
Let’s consider an ordering module. An order can be placed online or at a point of sale and can be paid in cash or by credit card. A customer placing an order online will receive an email confirmation.
public class Order
{
public void Checkout(Cart cart, Payment payment, bool informCustomer)
{
if (payment.PaymentMethod == PaymentMethod.CreditCard)
{
ChargeCard(payment, cart);
}
ReserveInventory(cart);
if (informCustomer)
{
NotifyCustomer(cart);
}
}
private void NotifyCustomer(Cart cart) {...}
private void ReserveInventory(Cart cart) {...}
private void ChargeCard(Payment payment, Cart cart) {...}
}
The above code breaks the SRP. Responsibilities are mixed up. What is more, point of sale orders will not need email confirmation nor inventory reservation. Cash transactions will not need credit card processing.
How to refactor this? Let’s make Order class abstract and Checkout method virtual.
public abstract class Order
{
protected readonly Cart _cart;
protected Order(Cart cart)
{
_cart = cart;
}
public virtual void Checkout()
{
// save the order in the database
}
}
Now let’s create classes OnlineOrder, PoSCreditOrder and PoCashOrder. All of those will inherit from Order class.
public class OnlineOrder : Order
{
private readonly Payment _payment;
private readonly INotificationService _notificationService = new NotificationService();
private readonly IPaymentProcessor _paymentProcessor = new PaymentProcessor();
private readonly IReservationService _reservationService = new ReservationService();
public OnlineOrder(Cart cart, Payment payment): base(cart)
{
_payment = payment;
}
public override void Checkout()
{
_paymentProcessor.ProcessCreditCard(_payment, _cart.TotalAmount);
_reservationService.ReserveInventory(_cart.Items);
_notificationService.NotifyCustomerOrderCreated(_cart);
base.Checkout();
}
}
Responsibilities regarding customer notification, inventory reservation and payment get extracted to separate single responsibility classes.
public class PoSCreditOrder : Order
{
private readonly Payment _payment;
private readonly IPaymentProcessor _paymentProcessor = new PaymentProcessor();
public PoSCreditOrder(Cart cart, Payment payment): base(cart)
{
_payment = payment;
}
public override void Checkout()
{
_paymentProcessor.ProcessCreditCard(_payment, _cart.TotalAmount);
base.Checkout();
}
}
public class PoSCashOrder : Order
{
public PoSCashOrder(Cart cart)
: base(cart)
{
}
}
Now, any changes to web order or credit card charging module will not affect other forms of sale.
Other examples of breaking SRP could be a Rectangle class with Render method or Person class with PrintPersonalDetails method. Rendering is not a responsibility of a rectangle!
References
SOLID Principles of Object Oriented Design – Pluralsight Online Training – Steve Smith
“Clean Code: A Handbook of Agile Software Craftsmanship” – Robert C. Martin
The Single Responsibility Principle Clean Code, Episode 9 By Uncle Bob
One thought on “Single Responsibility Principle”