The difference between Single Responsibility Principle and Separation of Concerns

design-patternssingle-responsibility

a)What is the difference between SRP and SoC? Perhaps that SRP is applied at class level, while SoC can be applied at system, subsystem, module, class or function levels.

b) If answer to a) is yes, is then SoC applied at class level a synonym for SRP?

thank you

Best Answer

The Single Responsibility Principle is about your code doing only 1 thing and you can split all functionality in several classes which all are meant for doing 1 specific thing. An example is a specific class for validation, doing some business logic, enriching a model, retrieving data, updating data, navigation, etc.

The Separation of Concerns is about your code not being tightly coupled to some other classes/systems. Using interfaces in your code helps a lot, this way you can loosly couple classes/systems to you code. A plusside on this is that it's easier to unit-test your code also. There are a lot of (IoC) frameworks which can help you achieve this, but you can implement such a thing yourself also of course.

An example of something SoC, but not having SRP

public class Foo
{
    private readonly IValidator _validator;
    private readonly IDataRetriever _dataRetriever;

    public Foo(IValidator validator, IDataRetriever dataRetriever)
    {
        _validator = validator;
        _dataRetriever = dataRetriever;
    }

    public NavigationObject GetDataAndNavigateSomewhereIfValid()
    {
        var data = _dataRetriever.GetAllData();

        if(_validator.IsAllDataValid(data))
        {
            object b = null;
            foreach (var item in data.Items)
            {
                b = DoSomeFancyCalculations(item);
            }

            if(_validator.IsBusinessDataValid(b))
            {
                return ValidBusinessLogic();
            }
        }
        return InvalidItems();
    }

    private object DoSomeFancyCalculations(object item)
    {
        return new object();
    }
    private NavigationObject ValidBusinessLogic()
    {
        return new NavigationObject();
    }

    private NavigationObject InvalidItems()
    {
        return new NavigationObject();
    }
}

As you can see, this code isn't tightly coupled to classes or other systems, because it only uses some interfaces to do stuff. This is good from a SoC standpoint.

As you can see this class also contains 3 private methods which do some fancy stuff. From a SRP standpoint, those methods should probably be placed within some classes of their own. 2 of them do something with navigation, which would fit in some INavigation class. The other does some fancy calculations on an item, this could probably be placed within an IBusinessLogic class.

Having something like this, you both have the SoC and SRP in place:

public class Foo
{
    private readonly IValidator _validator;
    private readonly IDataRetriever _dataRetriever;
    private readonly IBusinessLogic _businessLogic;
    private readonly INavigation _navigation;

    public Foo(IValidator validator, IDataRetriever dataRetriever, IBusinessLogic businessLogic, INavigation navigation)
    {
        _validator = validator;
        _dataRetriever = dataRetriever;
        _businessLogic = businessLogic;
        _navigation = navigation;
    }

    public NavigationObject GetDataAndNavigateSomewhereIfValid()
    {
        var data = _dataRetriever.GetAllData();

        if(_validator.IsAllDataValid(data))
        {
            object b = null;
            foreach (var item in data.Items)
            {
                b = _businessLogic.DoSomeFancyCalculations(item);
            }

            if(_validator.IsBusinessDataValid(b))
            {
                return _navigation.ValidBusinessLogic();
            }
        }
        return _navigation.InvalidItems();
    }
}

Of course you could debate if all this logic should be placed in the GetDataAndNavigateSomewhereIfValid method. This is something you should decide for yourself. To me it looks like this method is doing way too much stuff.