• 4 hours
  • Easy

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 3/28/24

“S” for the Single Responsibility Principle

The Single Responsibility Principle (SRP)

The first letter in the SOLID principles is “S” for the single responsibility principle (SRP), which you already encountered in Part 1 with the MVC architecture. As you learned, MVC separated our code for better readability, and each component – model, view, and controller – had its own purpose or responsibility.

What is responsibility?

Responsibility is the activity an application needs to do, which includes the methods, classes, and modules.

The goal for each of these types is to have only one job.

Now, that doesn’t mean a single class only has one method or property. All the properties and methods inside that class serve that single purpose the class is designed to do.

If something has too much responsibility, it’s coupled. For example, if a piece of code needs to know about class B in order to use class A, then A and B are coupled. Over time this causes complications and makes things harder to modify without having consequences to other parts of your code. We’ll discuss coupling more in Part 2.

Your goal is to have the right amount of coupling that allows for good cohesion in your application. Cohesion means how closely a class supports SRP. If you have high cohesion in a class, it means that you are following good SRP. If a class has multiple responsibilities, then it means it has a low cohesion, which is undesirable.  

Example 1: Not Following SRP

Here’s a simple example of a class that’s not following SRP:

public class Book
{
    public string Author { get; set; }
 
    public string Title { get; set; }
 
    public void Save()
    {
        // save to the database
    }
}

You’re probably thinking to yourself, “What’s wrong with it? Looks good to me.” But this class violates SRP because it has more than one reason to change:

  1. If you want to add a specific attribute for a book, for example, how many pages are in a book.

  2. If your database structure changes, you need to update how the book is saved. Maybe instead of the database, save it in a JSON file format.

Example 1: Corrected to Follow SRP

You can easily make this follow SRP by moving the  Save()  to a different class:

public class Book
{
    public string Author { get; set; }
 
    public string Title { get; set; }
}
 
public class DataService
{
    public void Save(Book book)
    {
        // save to the database
    }
}

Example 2: Not Following SRP

In this example, the CreatePost() method is doing too much and breaks SRP.

public class User
{
    public void CreatePost(DbContext dbContext, string postMessage)
    {
        try
        {
            dbContext.Add(postMessage);
        }
        catch(Exception ex)
        {
            dbContext.LogError("Error:", ex.ToString());
            File.WriteAllText("Log.txt", ex.ToString());
        }
    }
}

The CreatePost()  method has too many responsibilities:

  1. Add a new post to the database.

  2. Log an error to the database.

  3. Log an error to a local file.

Example 2: Corrected to Follow SRP

To correct this to have a higher cohesion and follow SRP, break up the responsibilities:

public class Post
{
    private ErrorLogger errorLogger = new ErrorLogger();
 
    public void CreatePost(DbContext dbContext, string postMessage)
    {
        try
        {
            dbContext.Add(postMessage);
        }
        catch(Exception ex)
        {
            errorLogger.Log(ex);
        }
    }
}
 
public class ErrorLogger
{
    private DbContext _dbContext;
 
    public ErrorLogger(DbContext dbContext)
    {
        _dbContext = dbContext;
    }
 
    public void Log(Exception ex)
    {
        _dbContext.LogError("Error:", ex.ToString());
        File.WriteAllText("Log.txt", ex.ToString());
    }
}

Now, there are two classes where each one has their own responsibility:

  1. Create a post.

  2. Log an error.

Let’s Recap!

Respecting the SRP (single responsibility principle) allows you to gain the following:

  1. The class is much easier to understand. When a class only does one thing, it becomes relatively self-explanatory.

  2. The class is easier to maintain. Changes to the class become more isolated, reducing the risk of breaking other parts of your application. 

  3. The class is more reusable. If your class has many responsibilities and only one is needed in another area of your application, then the other unused methods prevent reusability. But, if the class only has a single responsibility, you can reuse it without modifying it. 

Let’s move on the second letter in SOLID, “O,” for the open/closed principle.

Example of certificate of achievement
Example of certificate of achievement