The Single Responsibility Principle

Dec 11, 2009

The Single Responsibility Principle states that a class should only have one reason to change. Another possible title for this design principle would be the Single Reason to Change Principle.

Why is it important for a class to have a single reason to change and what are its benefits? One of the easiest ways to enhance the maintainability of a code base is to have it loosely coupled. In loosely coupled code, a change to one feature does not affect any other functionality. It is the opposite of spaghetti code where everything happens in one big method and changing how one functionality works very likely affects all the other functionality. And to get this loosely coupled code, each feature should be broken up into individual classes. If each class implements only one feature, then it only has one reason to change and when you change that feature you don’t have to worry about it breaking anything else in the code base.

A good example of a violation of the Single Responsibility Principle is having data validation and storage in the same class. Take a look at the code below as an example.

public virtual void Save(User user)
{
  if (string.IsNullOrEmpty(user.Name))
    throw new ValidationException("User name cannot be blank");

  using (var conn = new SqlConnection("connection string"))
  using (var command = conn.CreateCommand())
  {
    command.CommandText = "INSERT INTO USERS (Name) VALUES (:name)";
    command.Parameters.Add(new SqlParameter(":name", user.Name));
    command.ExecuteNonQuery();
  }
}

This code violates the Single Responsibility Principle because it performs two tasks: validating the object and persisting the object. These two responsibilities are orthogonal to each other and should be separated out to two classes since neither one affects the other.

Now that I have explained this design pattern, I want to give my opinion on its usage. I believe this principle is good to follow when designing applications but I don’t think it should followed to a T. I say this because I see some people take it too far. For instance, take for example the interface below.

public interface Modem
{
  public void Dial(string phoneNumber);
  public void Hangup();
  public void Send(string message);
  public string Receive();
}

Some would say the methods on this interface need separated out into 2 interfaces, one that takes care of the connection (Dial and Hangup) and another that takes care of the communication (Send and Receive). Personally I disagree. Yes, I can see how some could consider there being 2 responsibilities in this class, but then what is to keep the interface from being broken up into 4 interfaces, one for each method, because I could also see how Dial is a distinct responsibility from Hangup and Send is a different responsibility than Receive.

As far as implementing the Single Responsibility Principle, I personally advocate that there needs to be a sliding scale on how fine tuned the responsibilities are split out.

Before I expound on my position further, I need to introduce a term called responsibility group. A responsibility group is a set of responsibilities that correlate to each other in one way or another. The size of a responsibility group can be anywhere from large to small. The smaller the responsibility group, the more closely each responsibility correlates to each other, and the larger the group, the more loosely the responsibilities correlate to each other.

The smaller the application, the larger the responsibility group should be, and the larger the application, the smaller the responsibility group should be. The graph below shows a visual representation of what I’m talking about.

ApplicationResponsibility

I advocate this view as a result of my own experience. I volunteer my time at a non-profit organization where I have developed quite a few applications to help automate some of their administrative tasks. Many of these applications are quite small with less than 100 lines of written code. In these applications do I separate out the validation logic from the persistent logic? No, it’s not worth it. If I did I would very likely have more classes than I did lines of code. However, in my open source project (Linq to Excel) I have much smaller responsibility groups since it’s a larger project with many features.

One of the arguments for using this principle is making the code easier to maintain and add enhancements. But with small applications that serve a single specific purpose, it’s quite unlikely that they will change. And even if they do change and enhancements are added, the Single Responsibility Principle with smaller responsibility groups can be implemented by refactoring the code when the enhancements are added.

These are my thoughts and 2 cents worth on the Single Responsibility Principle. I know I do not follow the main stream of thought for this principle so I would love to receive feedback on my ideas on this principle. What is your experience with using this principle?

Posted by admin | Categories: Uncategorized |

Share with others

No Responses so far | Have Your Say!

Comments are closed.