1

Uncle Bob Martin frames the Single Responsibility Principle as "A class should have only one reason to change."

I wonder, is there any name for a converse principle like: "a single reason to change should impact only one class"? In other words, you shouldn't have to make changes scattered across multiple functions, classes, files, etc. to accomplish one goal.

closed as primarily opinion-based by Bart van Ingen Schenau, amon, gnat, 8bittree, Pieter B Nov 10 '17 at 7:48

Many good questions generate some degree of opinion based on expert experience, but answers to this question will tend to be almost entirely based on opinions, rather than facts, references, or specific expertise. If this question can be reworded to fit the rules in the help center, please edit the question.

  • I’ve thought about this often. The way to describe is that “change should be localized”. – RibaldEddie Oct 25 '17 at 18:44
  • 3
    I also wonder how would you follow this counterpart principle; for instance, consider a change like "wow, this X field of the Order screen is totally wrong, it has to be like that and calculated like this", which implies some actual change in several modules (eg: UI, backend, DB). – Emerson Cardoso Oct 25 '17 at 18:53
  • 1
    @EmersonCardoso what you describe is one of the attractions of model-driven frameworks like the Django admin app, where changing your model in one place triggers changes to both DB and UI. – wrschneider Oct 25 '17 at 19:54
  • 1
    Seems like following a single reason to change should impact only one class - will lead us back to "god" classes where any change will affect one class ;) – Fabio Oct 26 '17 at 10:34
1

I've often thought about it as well, here are my thoughts.

First, you probably delving too deep in this saying. It is basically an implementation detail of more fundamental principle called cohesion.

... cohesion refers to the degree to which the elements inside a module belong together.1 In one sense, it is a measure of the strength of relationship between the methods and data of a class and some unifying purpose or concept served by that class. In another sense, it is a measure of the strength of relationship between the class’s methods and data themselves.

It brings us to the first point: there should be only one such purpose. The second one is more subtle. It's about conforming a class name to its responsibilities. The abstraction level of these two should match. For example, here is Car's responsibility from my perspective:

class Car
{
    public function __construct()
    {
    }

    public function drive()
    {
        // 
    }
}

I don't care how exactly it drives. How fuel is given to an engine. So probably the following implementation violates SRP:

class Car
{
    public function __construct()
    {
    }

    public function drive()
    {
        //
    }

    public function giveFuelToEngine()
    {

    }
}

These are just different abstraction levels. Hence different reasons to change. So if a class is cohesive, if there is a single higher-level purpose, if its responsibilities conform to its name, the SRP would come naturally. SRP is just a practical consequence, it's not a goal by itself. Correct object identifying and endowing it with responsibilities is.

Second, these two phrases have to different intentions. A class should have only one reason to change is about a class that should be cohesive and serve only one goal, which could serve as a reason for a class to change. Otherwise, a single reason to change should impact only one class is about, well, that reason. Which of millions reasons would you choose? What about "Well, game development is not where our company succeeded, let's start a pub"? Is it a valid reason to change a single class? If you think it was excessive, ok, take Emerson Cardoso's comment. So your framework can handle that? Ok, what if it affects several distributed systems? BI service, marketing service, your customer's notification email, etc? Anyway, this simple change could incur changes in business-logic that none of the frameworks is capable of implementing automatically.

So my point is that this saying can be right or can be wrong -- it depends on that reason's level of abstraction.


So, wrapping it up, I can say that my goal is cohesive classes that implement correct abstraction levels. SOLID is just simplified implementational consequence of fundamental OO principles. It's just a form, not an essence.

Not the answer you're looking for? Browse other questions tagged or ask your own question.