SOLID Principles Using C# Series Part One – Single Responsibility Principle

By jonah on August 27, 2015

Introduction

SOLID are 5 important programming principles pinned down by Robert C. Martin in the 1990s. At first in a small application they may seem like over engineering, but as the application starts growing with the clients needs maintenance becomes a big issue. Which is where SOLID principles come into picture. They help to keep the application code clean, neat & easy to maintain basically decoupled.

SOLID helps make code human readable. The quote that comes to my mind by Martin Fowler

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

Let’s start with the first & the easiest principle Single Responsibility Principle, the theoretical definition of this principle is as follows

A class should have only a single responsibility. Only one potential change in the software’s specification should be able to affect the specification of the class.

In layman’s term, it means everything in your class, i.e. methods should have one responsibility & nothing more.

Let us take a simple example which violates SRP.

public class UserService
{
    public void Register(User model)
    {
        // Model validations
        if(model.Username.HasValue == false || model.Password.HasValue == false)
        {
            throw new ValidationException(model.GetErrors());
        }
 
        // Save to database
        _database.Save(model);
 
        // Code to send email
        var smtpClient = new SmtpClient();
        smtpClient.Send(mail);
    }
}

Just by going through the above code the first thought that comes to our mind is that clearly the Register method is doing things which it is not supposed to do. The Register method’s main responsibility is to Create User period!!! & it should delegate the work of Validation & Send Email to another class who should handle the responsibility.

One might say these are just a few lines of code and maintaining them is no big deal. But hey!! Who knows as the client needs keep changing and we may take in more registration information from the user to register which will increase our validation logic.

So now let’s try to bring in SRP into the above code.

public class UserService
{
    IDatabase _database = new Database();
    IValidatorService _validatorService = new ValidatorService();
    IEmailService _emailService = new EmailService();
 
    public void Register(User model)
    {
        // Check if the model valid
        if(_validatorService.ValidateUser(model) == false)
        {
            throw new ValidationException(model.GetErrors());
        }
 
        // Save the user to database
        _database.Save(model);
 
        // Code to send email
        _emailService.SendUser(user);
    }
}

So as you can see we have refactored the Register method as we have created separate Services called EmailService & ValidatorService which will handle their own domains i.e. sending email & validating model respectively.

Now the exception thrown can also be handled by another service, or a global error handler & make the UserService completely free of the task. Feel free to see the way it suits you. SRP is not something you’ll get right, right away. It’s a process an evolution.

Conclusion

SRP is the basics of a good architect software. Using it makes your code more human readable.