Blog




In this article I want to show, why it is a problem to have two (or more) reasons for a change or for the creation of something.

The event that made me think about this topic was an email of a friend of mine discussing some design issues in our exceptions library. He pointed out that there are two reasons for creating an exception class for Java:

  1. You want to catch an exception and handle it individually.
  2. You require specific information to be passed to the exception to document the context in which the exception has been raised.

I want to explain the problem with having two reasons in the light of

  1. Reducing Complexity
  2. Revealing Intention
  3. Reducing Conflict
 

If you are interested in a more detailed discussion on the problem according exception handling and our smartics exception library, please refer to Exceptions have two Responsibilities.

Reducing Complexity

The Single Responsibility Principle (the S in SOLID) is a design principle to make program code more understandable and easier to maintain.

There should never be more than one reason for a class to change.
Robert C. Martin

So reducing complexity by having only one responsibility is one of the reasons to have only one reason for a change.

Revealing Intention

In his book Practical API Design Jaroslav Tulach encourages to create APIs whose elements have a clear intention. One way to express expected API use is through modifiers of methods.

Access ModifierPrimary MeaningAdditional Meanings
publicMethod to be called by external clients of the API.Can be overridden by subclasses. Can also be called by subclasses.
public abstractMethod has to be implemented by subclasses.Method can be called by external clients.
public finalMethod to be called.None.
protectedMethod can be called by subclasses.Method can be overridden by subclasses.
protected abstractMethod needs to be overriden by subclasses.None.
protected finalMethod can be called by subclasses.None.

Source: Practical API Design, p. 172ff

Having only one meaning makes the intention clear. There is only one reason for the existence of a method.

Reducing Conflict

In her keynote The Power of Abstraction at QCon 2013 Barbara Liskov speaks about (beside other very interesting stuff) inheritance having two purposes (starting from minute 38, if you want to jump right into it):

  1. Implementation Technique
  2. Type Hierarchy

You can see inheritance as a way to provide a skeleton that indicates clearly, what has to be implemented to get things done faster. Basically you provide a type with a couple of methods to be implemented or overridden by subtypes and the task is done.

The second reason to use inheritance is again a design principle called Liskov Substitution Principle:

Objects of subtypes should behave like those of supertypes if used via supertype methods.

Barbara Liskov. The Liskov Substitution Principle

These two reasons conflict with each other. Where following the view of inheritance as an implementation technique is stressing the syntax, software development regularly heads into trouble, if it does comply with the second reason – which is purely semantic one. That is the reason why Barbara Liskov’s finding is the L in SOLID and a principle that is valued highly.

For this reason, reducing the possibility for conflicts, it would be better, if we had only one reason for selecting inheritance.

Conclusion

In a context where we are overwhelmed by alternative paths, it is a great relief to reduce our freedom of choice. At least as long as the one alternative that is most appropriate does not get cut off too early. But on the other side: a less optimal solution is often suitable enough in many circumstances. Getting things done cleanly is the way to go and deal with any technical dept as we have the knowledge to find a more suitable solution.

Trying to emphasis the notion of one reason is a benefit of any design. It leads us to solutions that are easier to understand, reduce the risk of doing something wrong and remove the danger of wasting time on decision making.

 


 

“Single responsibility principle” and the whole of SOLID are more or less for the non-thinking person. The SRP, as usually applied in OOP, is based on an either oversimplified or wrong understanding both of what responsibilities are and of what OOP is about.

Responsibilities, as they exist in the end user mental model, are system operations and have little to do with objects and nothing to do with classes. Neither objects nor classes have responsibilities: *roles* do. If you’re thinking responsibilities in terms of classes or objects, you’re just doing modules with instantiation. If you’re thinking of operations at the system level and role-level responsibilities, then you’re starting to think in an object-oriented sort of way.

See the many online materials by Trygve Reenskaug about this. You’ll find similar sentiments in Rebecca Wirfs-Brock’s latest book as well as in the Lean Architecture book.

James O. Coplien. (May 10, 2013 at 9:11 pm)

Dear Mr. Coplien,

thank you for your comment! I’m quite late with my response, but you gave me a long reading list and it took some time to catch-up. (wink) And I still have to admit that I am yet not fully through this list as I only read Mr. Reenskaug’s publications as far to get to realize that there are many treasures yet to dig up.

I cannot object to the points you addressed, but I would like to add a few comments.

SOLID

I agree that the SOLID principles are simplified, but none-the-less they form a tool to help beginners to start caring about design. To my experience they are the first step for software developers on their journey of learning software design. And with many tools, if applied by the “non-thinking” person, these principles will not automatically lead to “good design” (I put this in quotes since I do not specify what good design is). Probably by giving the false impression of being on a safe track, they may indeed wreak havoc. This is similar to designs where software developers apply each and every design pattern they read about. But this does not make those patterns worthless.

Maybe you are objecting to the naming of SRP as “principle”, if principles have to lead automatically to desirable results. Maybe the wording should have been “guiding rule”?

So if I understand you correctly: The SRP is about class design (“There should never be more than one reason for a class to change.”) and therefore it will not lead to a good OO design, where you set focus on the element’s roles and their associated responsibilities.

I have to agree. But I wanted to point out that we shouldn’t abandon all of SOLID – which my impression is, your first paragraph is all about.

Responsibility

When you emphasize the fact that only roles have responsibilities, you certainly help to get software designers on the right track. Your comment helped me to see this more clearly.

On the other hand, if you state that no other entities (to be fair: in your comment you restrict this to classes and – in parts – objects only) can possibly have responsibilities, I’m lacking the vocabulary to document the justification for the existence of a particular element. I’m currently reading George Fairbanks’ book “Just enough Software Architecture”. He writes:

“As you design a system, you allocate responsibilities to system elements. You can allocate responsibilities to elements of any model in any viewtype. […] System elements can have both functional and quality attribute responsibilities.” (p. 251)

Again it makes sense to emphasize focusing on each element’s role and reason about this role’s responsibilities. But is saying that an element has a certain responsibility not just a shortcut? If a single line of code checks that a user is who he pretends to be, is it wrong to say that the responsibility of this line of code is authentication? So I still have no solution how I should describe that some element’s justification for existence is its ‘responsibility’ to fulfill a requirement. I continue having this gut feeling that the “One-Reason-to-Change” thing is helping to organize code (not objects). And there seems to persist my misunderstanding.

Conclusion

Finally, on the bottom line, in response to your comment, I will try to make it more clearly when I talk about OO design and when I’m addressing “technical issues”, try to address how these aspects are connected, and put focus on roles.

Of course I missed some things. God is in the details! Maybe I just have to continue reading and learning – well that’s certainly a sure bet. (smile)

Thank you so much for your input!

Robert. (December 31, 2014 at 2:15 pm)


Link

Link

Posts

  • No labels