What is Single Responsibility Principle

In this article you will learn about the Single Responsibility Principle.

Introduction

The Single Responsibility Principle is a SOLID principle defined by Robert C. Martin. In principle it  says that an implementation (class / function) should perform only one task or implementation and it (class / function) should be changed for only one reason.

So in simple words it says that whatever the developer implements (class / function) in code during development should perform only one task and developer should only have one reason to change the implementation (class / function).

Wrong interpretation of the Principle

Most developers interpret to mean that a class should perform only one task. But it's not only classes, functions you implement in code during development should also perform only one task. So one should interpret it as meaning that an implementation should perform only one task.

Real Life Example of not following Single Responsibility Principle

What happens when one can do more than one task? The following is an image of an example of it.

One can perform multiple tasks, there is no question of that, but it's not going to provide quality / better output.

So to get good quality/better output of work, one should do one task at time.

Example of not following Principle in Application Development

In programming, in other words when developing code as in the following, the Order class is not following the principle.

  1. Public class OrderManager  
  2. {  
  3.     Public List < string > ValidateOrder()  
  4.     {  
  5.         //Code for validation    
  6.     }  
  7.     Public bool SaveOrder(OrderInfo order)   
  8.     {  
  9.         //Code for saving order    
  10.     }  
  11.     Public void NotifyCustomer()  
  12.     {  
  13.         //Code for notification     
  14.    }  
  15. }  
The preceding order class has the following responsibility:
  1. ValidateOrder: Validating an order placed by customer and return error message if any
  2. SaveOrder: Saving an order placed by the customer and returns true/false
  3. NotifyCustomer: Notifies the customer order is placed

Method not following the principle.

  1. public int SumOfAllCustomerOrder(int customerId)  
  2. {  
  3.     int sum = 0;  
  4.     var query = “Select * from order where customerid = ” + customerid;;  
  5.     //query orders    
  6.     foreach(Order in OrderCollection)   
  7.     {  
  8.         If(Order.Items.Count > 5)  
  9.         Sum += Order.Price;  
  10.     }  
  11.     return sum;  
  12. }  

The preceding method has the following responsibility:

  1. Method first all the orders
  2. It went through all orders in the collection and does some of that

Following Single Responsibility Principle

To make a class or function follow the Single Responsibility Principle, divide the responsibility by creating new classes or functions as in the following.

  1. Public Class OrderValidator   
  2. {  
  3.     Public List < string > Validate(Order order)   
  4.     { //code for validation}    
  5.     }  
  6.     Public Class Notifier   
  7.     {  
  8.         Public void Notify(string emailId)   
  9.         { //code for notification}    
  10.         }  
  11.         Public Class OrderManager   
  12.         {  
  13.             Private readonly OrderValidator orderValidator;  
  14.             Private readonly Notifier notifier;  
  15.             Public OrderManager(OrderValidator oValidator, Notifier nFier) {  
  16.                 orderValidator = oValidator;  
  17.                 notifier = nFier;  
  18.             }  
  19.             Public bool SaveOrder(OrderInfo orderInfo)   
  20.             {  
  21.                 //Validate order     
  22.                 orderValidator.Validate(orderInfo);    //code for saving order //this might be call to repository to save order     
  23.                     //notify after successful saving    
  24.                    notifier.Notify(orderInfo.EmailId);  
  25.             }  
  26.             Public List < OrderInfo > GetOrders(int customerId) { //code for getting order by cusotmerid}    
  27.             }

 

The preceding code shows the three classes that has only a single responsibility to perform.

For the method it will be like.

  1. public List < OrderInfo > GetOrder(int customerId)  
  2. {  
  3.     int sum = 0;  
  4.     var query = “Select * from order where customerid = ” + customerid;;  
  5.     //query orders    
  6.     return ordercollection;  
  7. }  
  8. public int SumOfAllCustomerOrder(int customerId)   
  9. {  
  10.     var OrderCollection = GetOrder(customerId);  
  11.     foreach(Order in OrderCollection)   
  12.     {  
  13.         If(Order.Items.Count > 5)  
  14.         Sum += Order.Price;  
  15.     }  
  16.     return sum;  
  17. }  

 

Note

Following the Single Responsibility doesn't mean one can create a class with only one method.

Disadvantages of not following Single Responsibility Principle

In programming if the developer creates a class/function that performs more than one task then that always causes problems in providing good quality. The following problems are related to a class performing more than one task:
  1. It's very difficult for the other developers (in other words developers unfamiliar with the class) to understand the class/function.
  2. It's difficult for the other developers to maintain the class/function or change the class/function.
  3. Writing test cases for the class/function also becomes difficult.

How to determine if the Single Responsibility Principle has not been followed

  1. Try to write a one line description of the class or method, if the description contains words like "And, Or, But or If" then that is a problem.

    An example of a description of a class as described above that does not follow the single responsibility principle is:

    “An Order class that performs order saving, notification to the customer and validates the order”.

  2. A class constructor takes more than three arguments or a method contains too many parameters.
  3. A class or method as an implementation that is is too long.
  4. A class that has low cohesion. Read more about cohesion : Cohesion

Reference: Clean code – Robert .C. Martin