Single Responsibility Principle

Use SRP guidelines to write loosely coupled and highly cohesive software units which can be reused. This makes the software extendable and maintainable. 

Classes and interfaces are basic units of a software. While writing a software we often overload a class with multiple responsibilities. As name suggests SRP states that a class should only perform one responsibility.

Let me code
Let’s take a look at the example below for more clarity on SRP.

    public class CampaignManager
    {
        public void LaunchCampaign(Campaign campaign)
        {
            try
            {
                // Code to launch the campaign
                this.NotifySubscribers(campaign);
            }
            catch (Exception exception)
            {
                string logMessage = string.Format("Exception occurred {0}", exception.Message);
                System.IO.File.AppendAllText("C:\\log.txt", logMessage);
            }
        }

        private void NotifySubscribers(Campaign campaign)
        {
            // Notify all the subscribers
        }
    }

At a glance you may like the code and decide to go along with this. Hold on, let me explain the problems in this code in the light of SRP. This class is performing 3 different responsibilities.

  1. Launch the campaign.
  2. Notify all the subscribers.
  3. If some exception occurs, log the exception with some message.

This is the violation of SRP. In future if we have to change the way we log our exception messages e.g. we want to log messages to database rather a file or we want our notifier to ignore certain subscribers, we will need to change CampaignManager which leaves our software in less maintainable and less extendable state.

Let’s try to resolve this problem by dividing the responsibilities among multiple classes instead of one.

  1. CampaignManager will launch the campaign.
  2. Notifier class will be responsible for publishing to the subscribers.
  3. Logger class will be responsible for logging the exceptions and errors.

This is how it would look like.

    public class CampaignManager
    {
        Notifier notifier = new Notifier();
        Logger logger = new Logger();
        public void LaunchCampaign(Campaign campaign)
        {
            try
            {
                // Code to launch the campaign
                notifier.NotifySubscribers(campaign);
            }
            catch (Exception exception)
            {
                string logMessage = string.Format("An Exception occurred. {0}", exception.Message);
                logger.Error(logMessage, exception);
            }
        }
    }

    internal class Logger
    {
        public void Error(string logMessage, Exception exception)
        {
            //Log error mesaage to Application Event Log
        }
    }

    internal class Notifier
    {
        public void NotifySubscribers(Campaign campaign)
        {
            // Notify subscribers
        }
    }

This is how we resolve the SRP violation in any code. This makes our classes highly cohesive, reusable and very loosely coupled. So now if we need to change something related to notifications, we will only change the Notifier class and same goes for Logger as well.

Leave a Reply