
Single Responsibility Principle
The second article in the SOLID Principles series describes the Single Responsibility Principle (SRP). The SRP states that each class or similar unit of code should have one responsibility only and, therefore, only one reason to change.
The Principle
The Single Responsibility Principle (SRP) states that there should never be more than one reason for a class to change. This means that every class, or similar structure, in your code should have only one job to do. Everything in the class should be related to that single purpose. It does not mean that your classes should only contain one method or property. There may be many members as long as they relate to the single responsibility. It may be that when the one reason to change occurs, multiple members of the class may need modification. It may also be that multiple classes will require updates.
Application of the SRP can change your code considerably. One key change is that the classes in your projects become smaller and cleaner. The number of classes present in a solution may increase accordingly so it is important to organise them well using namespaces and project folders. The creation of classes that are tightly focussed on a single purpose leads to code that is simpler to understand and maintain.
A further benefit of having small, cohesive classes is that the chances of a class containing bugs is lowered. This reduces the need for changes so the code is less fragile. As the classes perform only one duty, multiple classes will work together to achieve larger tasks. Along with the other principles this permits looser coupling. It can also make it easier to modify the overall software, either by extending existing classes or introducing new, interchangeable versions.
Example Code
To demonstrate the application of the SRP, we can consider an example C# class that violates it and explain how the class can be refactored to comply with the principle:
public class OxygenMeter
{
public double OxygenSaturation { get; set; }
public void ReadOxygenLevel()
{
using (MeterStream ms = new MeterStream("O2"))
{
int raw = ms.ReadByte();
OxygenSaturation = (double)raw / 255 * 100;
}
}
public bool OxygenLow()
{
return OxygenSaturation <= 75;
}
public void ShowLowOxygenAlert()
{
Console.WriteLine("Oxygen low ({0:F1}%)", OxygenSaturation);
}
}
The code above is a class that communicates with a hardware device to monitor the oxygen levels in some water. The class includes a method named "ReadOxygenLevel" that retrieves a value from a stream generated by the oxygen monitoring hardware. It converts the value to a percentage and stores it in the OxygenSaturation property. The second method, "OxygenLow", checks the oxygen saturation to ensure that it exceeds the minimum level of 75%. The "ShowLowOxygenAlert" shows a warning that contains the current saturation value.
There are at least three reasons for change within the OxygenMeter class. If the oxygen monitoring hardware is replaced the ReadOxygenLevel method will need to be updated. If the process for determining low oxygen is changed, perhaps to include a temperature variable, the class will need updating. Finally, if the alerting requirements become more sophisticated than outputting text to the console, the ShowLowOxygenAlert method will need to be rewritten.
24 December 2010