SOLID - Single Responsibility Principle
Single Responsibility Principle (SRP) is the first amongst the five design principles stipulated by SOLID.
Single Responsibility Principle
A class should have one and only one reason to change, meaning that a class should only have one job.
Let’s understand better with an example
Lets take an example of a journal. We could write code to implement a personal journal as follows…
using System;
using System.Collections.Generic;
namespace SOLIDPrinciples.SingleResponsibilityPrinciple
{
public class Journal
{
private readonly List<string> entries = new List<string>();
private static int count =0;
public int AddEntry(string text)
{
System.Console.WriteLine($"{++count}: {text}");
return count;
}
public void RemoveEntry(int index)
{
entries.RemoveAt(index);
}
public override string ToString()
{
return string.Join(Environment.NewLine, entries);
}
}
class Program
{
static void Main(string[] args)
{
Journal journalEntries = new Journal();
journalEntries.AddEntry("I had a good time yesterday with family");
journalEntries.AddEntry("Today was a busy day filled with work");
System.Console.WriteLine(journalEntries.ToString());
}
}
}
As shown in the code, our class Journal
has methods to add and remove entries from it. So far our Journal
class is behaving as required - with a single responsibility.
Now, consider the case where we want to extend this by being able to save the journal entries in a file (persist data). We’ll add the following 2 methods to the Journal
class.
//Extending the class
public void SaveToFile(string fileName)
{
File.WriteAllText(fileName, ToString());
}
public Journal Load(string fileName)
{
//Code to read from file, populate the Journal object and return it
}
Now these 2 methods definitely help adding a persistence layer, however they violate the SRP principle. Here in addition to saving and removing entries from the Journal
, the Journal
has to also manage persistence. This means that there are more than one reasons for a change to this class which violates the SRP principle (as per which there should be only one reason for change in a class).
Hence, to adhere to SRP we can tackle the above in a different way.
We will create a new class Persistence
as follows…
public class Persistence
{
public void SaveToFile(string fileName, Journal journal, bool overwrite = false)
{
if(overwrite || !string.IsNullOrEmpty(fileName))
File.WriteAllText(fileName, journal.ToString());
}
}
This class can now be instantiated and called from the main method as follows…
class Program
{
static void Main(string[] args)
{
Journal journalEntries = new Journal();
journalEntries.AddEntry("I had a good time yesterday with family");
journalEntries.AddEntry("Today was a busy day filled with work");
System.Console.WriteLine(journalEntries.ToString());
string fileName = "c:\file.txt";
Persistence persist = new Persistence();
persist.SaveToFile(fileName, journalEntries, true);
}
}
As is now evident, henceforth if any changes are required in the persistence layer it will not require the Journal
class to be modified and hence SRP will not be violated.