Tech Point Fundamentals

Sunday, December 26, 2021

Single Responsibility Principle of SOLID | SRP

Single Responsibility Principle of SOLID | SRP

Single-Responsibility-Principle

SOLID Principles are one of the mandatory questions in each and every interview. This is the second part of the SOLID Design Principle. In this part, we will walk through the first SOLID Design Principle i.e "Single Responsibility Principle" (SRP) in detail with live real examples. 

Please read the previous part over here by below link:


SOLID Design Principles


Watch our videos here




Introduction


In the SOLID acronym, the first letter "S" represents the "Single Responsibility Principle" of Object-Oriented Design (OOD). The Single Responsibility Principle focuses on the responsibility or role of any function or module.


The SOLID Principle was first introduced by the famous Computer Scientist Robert C. Martin (Uncle Bob) in his paper "Design Principles and Design Patterns" in the year 2000. But the SOLID acronym was introduced later around 2004 by Michael Feathers.


The Single Responsibility Principle is based on one class one responsibility, and one reason for the change


In Object-Oriented Programming, the class represents the real-world entity where properties define the attributes and the methods of the class specify the behavior associated with that entity. So class objects should not have any unrelated behavior. To achieve this one should just follow the Single Responsibility Principle of OOD.




Single Responsibility Principle (SRP)


The Single Responsibility Principle is the first SOLID Design Principle. The Single Responsibility Principle states that a class should do only one thing and therefore it should have only one reason to change. Single denotes some work in isolation.


Every module or class should have responsibility only over a single part of the functionality provided by the software, and that responsibility should be entirely encapsulated by the class.


Responsibility is the work or action that each part of your system i.e methods, classes, packages, or modules are assigned to do. On the other hand, a change is an alteration or a modification of the existing code. Too much responsibility leads to coupling.


The term "Single Responsibility Principle" was introduced by Robert C. Martin in an article by the same name as part of his "Principles of Object-Oriented Design" in the year 2003 in his book "Agile Software Development, Principles, Patterns, and Practices".


This principle is based on the Principle of Cohesion as described by Tom DeMarco in his book "Structured Analysis and System Specification" and Meilir Page-Jones in "The Practical Guide to Structured Systems Design".


Cohesion is a measure of the degree to which the elements of the module or class are functionally related. It measures the degree to which all elements directed towards performing a single task are contained in the component, module, or class. A good software design will have high cohesion.


Coupling is the measure of the degree of interdependence between the modules. Coupling is the level of awareness or details a part of the system knows about another part of the system. For example, if client code needs to know class B in order to use class A, then A and B are said to be coupled. A good software design should have low coupling




Definition of SRP


According to Robert C. Martin, the Single-responsibility Principle (SRP) states that:


A class or module should have one, and only one, reason to be changed.


In other words: 


"There should never be more than one reason for a class to change"


The Single Responsibility Principle also dictates that "Gather together the things that change for the same reasons. Separate those things that change for different reasons".


Studies of historic data from legacy software systems have identified three specific causes of this change: adding new features, correcting faults, and restructuring code to accommodate future changes.


In the context of the SRP, the term "reason" and "responsibility" is not as simple as it is in reading. According to Robert C. Martin, these terms have a broader meaning above our thinking i.e audience or user (aka, actor) and their role.


The users of the application or system who are served by a particular module or class will be the ones who request changes to it.  For example DBAs, Software Architects, or end-users.


It is much easier to imagine actors doing those roles and associating our audience with those actors. So if our audience defines reasons for change, the actors define the audience.


According to Robert C. Martin: "A responsibility is a family of functions that serves one particular actor."


So actors become a source of change for the family of functions that serves them. If their needs change, that specific family of functions must also change to accommodate their needs.


According to Robert C. Martin: "An actor for a responsibility is the single source of change for that responsibility."


So according to the Single Responsibility Principle, when writing a class, we have to think about the problem domain (entity), business needs, and application architecture. It is very subjective, which makes implementing this principle harder than it seems. 





Explanation


So, every class should have only one responsibility and if every class has only one job there should have one and only one reason to change in that class. 


The responsibility of a class is considered to be one reason to change. If we have two reasons to change for a class, we have to split the functionality into two classes. Each class will handle only one responsibility and if there is a change in the future we need to make only one change we are going to make it in the class which handles it only.


Nowadays the Micro-services closely follow Single Responsibility. So any change in a single service does not affect the other services at all.





Advantages of Following SRP


In the agile world, requirements change over time, and when changes came it affects and leads to change at least one class. If you define multiple responsibilities in a class, changes made due to one responsibility may also affect the other responsibility which the class is doing. This might lead to any unexpected side effects.


Now you might think that this is not a big deal to change in a class!!!


Wait...Wait... Please watch the Fragile Base Class Problem video here and the Polymorphic Dilemma here and think once again.


The Single Responsibility Principle prevents the GOD Object Problem also. A God Object is an Object that knows everything and does everything.


So a single miner change in a class functionality affects all the classes and components that depend on the changed class. Also depending on your change, you might need to update the dependencies or recompile the dependent classes even though they are not directly affected by your change.


On the other hand, when you follow the SRP, the code will be pretty self understandable easily. This also reduces the number of bugs, and unit testing efforts as well.




Example


public class User
{
 	public void InitializeDBConnetion()
 	{
 	    // Code for DB Connection
 	}

 	public void AddUser(UserModel mode)
 	{ 
 	    // Code to save user details
 	}

 	public void Logger(string message)
 	{
 	    // Code to write logs into the text file
 	}

 	public void SendEmail(string message)
 	{
 	    // Code to send different emails to the user
 	}
}
    
public class UserModel
{
  public int Id { get; set; }
  public string Email { get; set; }
  public string Password { get; set; }
}        



The above implementation does not obey the SRP guideline at all. Here we are assigning multiple responsibilities to the user class. 


If we write the database logic, business logic, logger logic, and email communication logic as well in a single class, then our class performs multiple responsibilities. Then it becomes very difficult to change one responsibility without breaking the other responsibilities.




According to the SRP, each and every class must have a single responsibility and single reason for the change. So let's implement this for the above example:



public class User
{
  public void AddUser(UserModel mode)
  {
      // Code to save user details
  }
}

public interface ILogger
{
    void Info(string info);       
    void Error(string message, Exception ex);
}

public class Logger : ILogger
{
    public void Error(string message, Exception ex)
    {
       // Code for error logs
    }

    public void Info(string info)
    {
        // Code for info logs
    }
}

public class MailSender
{
    public string From { get; set; }
    public string To { get; set; }
    public string Subject { get; set; }
    public string Body { get; set; }

    public void SendEmail()
    {
        // Code for sending the mail
    }
}

public class DBCOnnection
{
    // Code to open and close the DB Connection
}    



So our code now follows the Single Responsibility Principle because we have separated each and every task or responsibility into a separate class.




Recommended Articles


Method Overloading and Overloading Dilemma - Part 2
Static Polymorphism C#
Interface Virtual Method in C#
Method Overriding in C#




Thanks for visiting this page. Please follow us on Twitter, Facebook, LinkedIn, Telegram, Youtube, and Quora for regular updates.




External Reference Links


Principles of OOD

GRASP Principles

SOLID Principles

Single Responsibility Principle


No comments:

Post a Comment

Please do not enter any HTML. JavaScript or spam link in the comment box.