Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Single Responsibility Principle: do all public methods in a class have to use all class dependencies?

Say I have a class that looks like the following:

internal class SomeClass
{
    IDependency _someDependency;

    ...


    internal string SomeFunctionality_MakesUseofIDependency()
    {
    ...
    }
}

And then I want to add functionality that is related but makes use of a different dependency to achieve its purpose. Perhaps something like the following:

internal class SomeClass
{
    IDependency _someDependency;

    IDependency2 _someDependency2;

    ...


    internal string SomeFunctionality_MakesUseofIDependency()
    {
    ...
    }

    internal string OtherFunctionality_MakesUseOfIDependency2()
    {
    ...
    }
}

When I write unit tests for this new functionality (or update the unit tests that I have for the existing functionality), I find myself creating a new instance of SomeClass (the SUT) whilst passing in null for the dependency that I don't need for the particular bit of functionality that I'm looking to test.

This seems like a bad smell to me but the very reason why I find myself going down this path is because I found myself creating new classes for each piece of new functionality that I was introducing. This seemed like a bad thing as well and so I started attempting to group similar functionality together.

My question: should all dependencies of a class be consumed by all its functionality i.e. if different bits of functionality use different dependencies, it is a clue that these should probably live in separate classes?

like image 931
jpoh Avatar asked Jul 13 '09 09:07

jpoh


People also ask

Does SRP apply to methods?

The Single Responsibility Principle applies to the software that we develop on different levels: methods, classes, modules, and services (collectively, I'll call all these things components later in this article). So, the SRP states that each component should have a single responsibility.

Which is the correct in relation to the single responsibility principle?

The Single Responsibility Principle (SRP) The idea behind the SRP is that every class, module, or function in a program should have one responsibility/purpose in a program. As a commonly used definition, "every class should have only one reason to change".

Which is correct in relation to the single responsibility principle everything in a codebase should be doing only one thing?

The Single Responsibility Principle (SRP) states that each software module should have one and only one reason to change. In other words, one should gather together the things that change for the same reasons. Separate those things that change for different reasons.

Which of the following statements describe the single responsibility principle of the solid object?

Single-responsibility Principle (SRP) states: A class should have one and only one reason to change, meaning that a class should have only one job.


2 Answers

When every instance method touches every instance variable then the class is maximally cohesive. When no instance method shares an instance variable with any other, the class is minimally cohesive. While it is true that we like cohesion to be high, it's also true that the 80-20 rule applies. Getting that last little increase in cohesion may require a mamoth effort.

In general if you have methods that don't use some variables, it is a smell. But a small odor is not sufficient to completely refactor the class. It's something to be concerned about, and to keep an eye on, but I don't recommend immediate action.

like image 81
Uncle Bob Avatar answered Oct 05 '22 23:10

Uncle Bob


Does SomeClass maintain an internal state, or is it just "assembling" various pieces of functionality? Can you rewrite it that way:

internal class SomeClass
{
    ...


    internal string SomeFunctionality(IDependency _someDependency)
    {
    ...
    }

    internal string OtherFunctionality(IDependency2 _someDependency2)
    {
    ...
    }
}

In this case, you may not break SRP if SomeFunctionality and OtherFunctionality are somehow (functionally) related which is not apparent using placeholders.

And you have the added value of being able to select the dependency to use from the client, not at creation/DI time. Maybe some tests defining use cases for those methods would help clarifying the situation: If you can write a meaningful test case where both methods are called on same object, then you don't break SRP.

As for the Facade pattern, I have seen it too many times gone wild to like it, you know, when you end up with a 50+ methods class... The question is: Why do you need it? For efficiency reasons à la old-timer EJB?

like image 24
insitu Avatar answered Oct 05 '22 23:10

insitu