Andy Crouch - Code, Technology & Obfuscation ...

Single Responsibility Methods

Man Sitting On Clock Rug

Photo: Kevin Ku - Unsplash

The Single Responsibility Principle is a core element of the SOLID Principles. Wikipedia states that the principle stipulates that

“a class should have only a single responsibility (i.e. changes to only one part of the software’s specification should be able to affect the specification of the class).”

Most developers agree with this approach and structure their code accordingly. Then they create methods in those classes with words like “And” and “Or” in the name. This is a clear code smell that your method is doing too many things. Why structure our classes following SRP and then tool them with confusing methods?

As an example, I have often seen code like

public class DataFileParser
{
    public List<Entity> DownloadAndParse(string filePath)
    {
        // long code block that validates that the 
        // filepath exists & downloads it
        // and parses it to a list of objects of type Entity
    }
}

Now I am not interested in showing the actual implementation. What I am showing is that it is common to see a method that does more than one thing. In order for the method to complete it needs to do three discrete steps.

public class DataFileParser
{
    public bool FileExists(string filePath)
    {
        // validate that file exists
    }
    
    public File Download(string filePath)
    {
        // download file
    }
    
    public List<Entity> ParseToList(File file)
    {
        // parses it to a list of objects of type Entity
    }
}

As an aside, by refactoring in this method there is a clear violation of SRP at the class level. FileExists and Download methods should clearly be refactored into a separate class.

public class DataFileParser
{
    public List<Entity> ParseToList(File file)
    {
        // parses it to a list of objects of type Entity
    }
}

public class DataFile
{
    readonly File _file;

    public DataFile(string filePath)
    {
        _file = new File(filePath);
    }

    public bool FileExists()
    {
        // validate that code exists
    }
    
    public File Download()
    {
        // download file
    }
}

This simple refactoring results in two classes that now have a single responsibility. Each method has a single responsibility as well. This improves readability and more importantly makes the methods easier to test. It also makes clear the intent of the methods which reduces the ability for it to cause side effects. Side effects from badly designed methods have lost me countless hours over the years. A final reason to structure your methods in this way relates to reuse. By limiting the methods to a single responsibility you will end up increase reuse significantly as you can chain calls up in various ways that you just can’t when they are grouped together as one method.

To end I will include a quote from Robert C Martin on the subject of SRP

“Gather together the things that change for the same reasons. Separate those things that change for different reasons.”

If you’d like to discuss my thoughts on method design then message me via twitter or email.