Single Responsibility Principle (SRP)

Introduction 

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

Single Responsibility Principle (SRP) 

  • The Single Responsibility Principle states that a class should have one and only one reason for the change.
  • The benefits of SRP include:
    • Reduction in complexity of code
    • Increased readability, extensibility, and maintenance
    • Reusability and reduced errors
    • Better testability
  • The classes and interfaces in an application often become bloated when they have to perform too many different responsibilities.
  • The basic idea behind SRP is that two or more separate responsibilities should be separated into distinct classes or modules - it is a bad design approach to couple different responsibilities in the same class if such responsibilities might change over time
  • The class should have one purpose, if you want to change or modify the class then it should be in one area(class).
  • Class size should not be more than 40-50 lines. If the screen is getting a scrollbar when you open your class then we need to think about how can we divide the class into different classes.
Consider the below example:
  1. namespace ConsoleUI  
  2. {  
  3.     class Program  
  4.     {  
  5.         static void Main(string[] args)  
  6.         {  
  7.             Console.WriteLine("Welcome to the Application");  
  8.   
  9.             //Ask for Information  
  10.             Person user = new Person();  
  11.             Console.WriteLine("What is your First Name");  
  12.             user.FirstName = Console.Readline();  
  13.             Console.WriteLine("What is your Last Name");  
  14.             user.LastName = Console.Readline();  
  15.   
  16.             //Ask for Validation  
  17.             if(String.IsNullOrWhiteSpace(user.FirstName))  
  18.             {  
  19.                  Console.WriteLine("You didnt have valid First Name");  
  20.                  Console.Readline();  
  21.                  return;  
  22.             }    
  23.             if(String.IsNullOrWhiteSpace(user.LastName))  
  24.             {  
  25.                  Console.WriteLine("You didnt have valid Last Name");  
  26.                  Console.Readline();  
  27.                  return;  
  28.             }  
  29.   
  30.             //Final output to User  
  31.             Console.WriteLine($"Your UserName is {user.FirstName}{user.LastName}");  
  32.             Console.Readline();  
  33.         }  
  34.     }  
  35. }  
What problem we can figure out from the above program,
  • When the project contains 50 lines of code and the developer wants to change the code as per the new requirement, it can be managed. However, consider that if in 6 months when the code exceeds 500 lines and all lines are doing different-different stuff, how the developer is going to manage everything?
  • A new requirement comes. Instead of “What is your First Name” it should be “What is your First Name Sir/Madam”. With these small lines of code, it is manageable. But consider a scenario,(after 6 months) code has 5 sections- (Name, Age, Gender, Education, Family background ). The developer needs to figure out from where we are taking this information in code.
  • Merging the code if multiple developers are working at the same time for different module
  • The problem for the long run will be:
    • It will lead to the time-consuming task as code complexity increases
    • The risk of breaking the code is more. Even for small change, we need to test the whole project
    • Maintaining the application is difficult
Solution
 
It can vary from developer to developer:
 
 
In the above program, we can identify 5 different sections that are independent of each other:
  • Everything related to Printing output:
    • Some are welcome message
    • Some are requesting information message
    • Some are validation message
    • Some are Final Output message
  • Hold the Screen
  • Creating User and requesting information
  • Validation
  • Perform the Final output process
Let's create a module that will show all messages to Users.
 
In the future, if a user logs in to any module, we need to show a welcome message. In this case, we will refer to the class. 
  1. public class WelcomeMessage  
  2. {  
  3.     public static void DisplayWelcomeMessage()  
  4.     {  
  5.         Console.WriteLine("Welcome to the Application");  
  6.     }  
  7. }  
In the future, any validation message, we will refer to the below class.         
  1. public class ValidationMessage  
  2. {  
  3.     public static void DisplayValidationErrorMessage(string fieldName)  
  4.     {  
  5.         Console.WriteLine($"You didnt give us valid {fieldName}");  
  6.     }  
  7. }  
In the future, any request we want to make to the user, we will use the below class.      
  1. public class PersonalInformationMessage  
  2. {  
  3.     public static void DisplayPersonalInformationMessage(string fieldName)  
  4.     {  
  5.         Console.WriteLine($"What is your {fieldName}");  
  6.     }  
  7. }  
We will refer to the below class for any activity to highlight to the user after account creation:       
  1. public class AccountGeneratorMessage  
  2. {  
  3.     public static void DisplayAccountGeneratorMessage(Person user)  
  4.     {  
  5.         Console.WriteLine($"Your UserName is {user.FirstName}{user.LastName}");  
  6.   
  7.     }  
  8. }  
Before closing the application, if any necessary steps need to be done, we will use the below class:
  1. public class EndApplication  
  2. {  
  3.    public static void EndProcess()  
  4.     {  
  5.          Console.Readline();  
  6.     }  
  7. }  
All the required data from the user will be requested from the below module:
  1. public class PersonalDataCapture  
  2. {  
  3.   
  4.     public static Person Capture()  
  5.     {  
  6.             Person user = new Person();  
  7.             PersonalInformationMessage.DisplayPersonalInformationMessage(user.FirstName)  
  8.             user.FirstName = Console.Readline();  
  9.             PersonalInformationMessage.DisplayPersonalInformationMessage(user.LastName)  
  10.             user.LastName = Console.Readline();  
  11.             return user;  
  12.     }  
  13. }  
All personal validation logic will use the below class:
  1. public class PersonalValidation  
  2. {  
  3.   
  4.     public static bool Validate(Person user)  
  5.     {  
  6.             if(String.IsNullOrWhiteSpace(user.FirstName))  
  7.             {  
  8.                 ValidationMessage.DisplayValidationErrorMessage("First Name");  
  9.                 return false;  
  10.             }    
  11.              if(String.IsNullOrWhiteSpace(user.LastName))  
  12.             {  
  13.                 ValidationMessage.DisplayValidationErrorMessage("Last Name");  
  14.                 return false;  
  15.             }    
  16.     }  
  17. }  
All account creation steps will be performed in the below class:
  1. public class AccountGenerator  
  2. {  
  3.     public static CreateAccount(Person user)  
  4.     {  
  5.         AccountGeneratorMessage.DisplayAccountGeneratorMessage(user);  
  6.     }  
  7. }  
The final program will look like as shown below:
  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.            WelcomeMessage.DisplayWelcomeMessage();  
  6.   
  7.             //Ask for Information  
  8.             Person user = PersonalDataCapture.Capture();  
  9.   
  10.             //Ask for Validation  
  11.             bool isUserValid = PersonalValidation.Validate(user);  
  12.             if(isUserValid==false)  
  13.             {  
  14.                 EndApplication.EndProcess();  
  15.                 return;  
  16.             }  
  17.             //Final output to User  
  18.             AccountGenerator.CreateAccount(user);  
  19.             EndApplication.EndProcess();  
  20.         }  
  21.     }  
The single responsibility principle should be always in our mind while writing code. It will help not only you but the other developers that need to maintain your code later as well.
 
The whole idea I used from Tim Corey
 
The link is here.