'Are SOLID principles really solid?

The design pattern the first letter in this acronym stands for is the Single Responsibility Principle. Here is a quote:

the single responsibility principle states that every object should have a single responsibility, and that responsibility should be entirely encapsulated by the class.

That's simple and clear until we start to code. Suppose we have a class with a well defined single responsibility. To serialize the class instances we need to add special atrributes to that class. So now the class has another responsibility. Doesn't that violate the SRP?

Let's see another example - an interface implementation. When we implement an interface we simply add other responsibilities, say disposing of its resources or comparing its instances or whatever.

So my question. Is it possible to strictly keep to SRP? How can it be done?



Solution 1:[1]

As you will one day discover, none of the most known principles in software development can be 100% followed.

Programming is often about making compromises - abstract pureness vs. code size vs. speed vs.efficiency.

You just need to learn to find the right balance: not let your application fall into abyss of chaos but not tie yourself hands with multitude of abstraction layers.

Solution 2:[2]

I don't think that being serializable or disposable amounts to multiple responsibilities.

Solution 3:[3]

Well I suppose the first thing to note is that these are just good Software Engineering principles - you have to apply judgment also. So in that sense - no they are not solid (!)

I think the question you asked raises the key point - how do you define the single resposibility that the class should have?

It is important not to get too bogged down on details when defining a responsibility - just because a class does many things in code dosn't mean that it has many responibilities.

However, please do stick with it though. Although it is probably impossible to apply in all cases - it is still better than having a single "God Object" (Anti-Pattern) in your code.

If you are having problems with these I would recommend reading the following:

  • Refactoring - Martin Fowler: Although it is obviously about refactoring, this book is also very helpful in displaying how to decompose problems into their logical parts or resposibilities - which is key to SRP. This book also touches on the other principles - however it does it in a lot less academic way than you may have seen before.

  • Clean Code - Robert Martin: Who better to read than the greatest exponent of the SOLID principles. Seriously, I found this to be a really helpful book in all areas of software craftsmanship - not just the SOLID principles. Like Fowler's book, this book is pitched at all levels of experiance so I would recommend to anyone.

Solution 4:[4]

To better understand the SOLID principles you have to understand the problem that they solve:

Object-oriented programming grew out of structured/procedural programming--it added a new organizational system (classes, et al) as well as behaviors (polymorphism, inheritance, composition). This meant that OO was not seperate from structured/procedural, but was a progression, and that developers could do very procedural OO if they wanted.

So... SOLID came around as something of a litmus test to answer the question of "Am I really doing OO, or am I just using procedural objects?" The 5 principles, if followed, means that you are quite far to the OO side of the spectrum. Failing to meet these rules doesn't mean you're not doing OO, but it means its much more structural/procedural OO.

Solution 5:[5]

There's a legitimate concern here, as these cross-cutting concerns (serialization, logging, data binding notification, etc.) end up adding implementation to multiple classes that is only there to support some other subsystem. This implementation has to be tested, so the class has definitely been burdened with additional responsibilities.

Aspect-Oriented Programming is one approach that attempts to resolve this issue. A good example in C# is serialization, for which there is a wide range of different attributes for different types of serialization. The idea here is that the class shouldn't implement code that performs serialization, but rather declare how it is to be serialized. Metadata is a very natural place to include details that are important for other subsystems, but not relevant to the testable implementation of a class.

Solution 6:[6]

The thing to remember about design principles is there's always exceptions, and you wont always find that your scenario/implementation matches a given principle 100%.

That being said, adding attributes to the properties isn't really adding any functionality or behavior to the class, assuming your serialization/deserialization code is in some other class. You're just adding information about the structure of your class, so it doesn't seem like a violation of the principle.

Solution 7:[7]

I think there are many minor, common tasks a class can do without them obscuring the primary responsibility of a class: Serialisation, Logging, Exception Handling, Transaction Handling etc.

It's down to your judgement as to what tasks in your class constitute an actual responsibility in terms of your business/application logic, and what is just plumbing code.

Solution 8:[8]

So, if instead of designing one "Dog" class with "Bark", "Sleep" and "Eat" methods, I must design "AnimalWhoBarks", "AnimalWhoSleeps", "AnimalWhoEats" classes, etc? Why? How does that make my code any better? How am I supposed to simply implement the fact that my dog will not go to sleep and will bark all night if he hasn't eat?

"Split big classes in smaller ones", is a fine practical advice, but "every object should have a single responsibility" is an absolute OOP dogmatic nonsense.

Imagine the .NET framework was written with SRP in mind. Instead of 40000 classes, you would have millions.

Generalized SRP ("Generalized" is the important word here) is just a crime IMHO. You can't reduce software development to 5 bookish principles.

Solution 9:[9]

By changing your definition of "single responsibility" - SOLID principles are quite liquid and (like other catchy acronyms of acronyms) don't mean what they seem to mean.

They can be used as a checklist or cheat sheet, but not as complete guidelines and certainly not learning material.

Solution 10:[10]

What is a responsibility? In the words of Robert C. Martin (aka. Uncle Bob) himself:

SRP = A class should have one, and only one, reason to change.

The "single responsibility" and "one reason to change", in SRP, has been a source of much confusion (e.g. Dan North, Boris). Likely since responsibilities of pieces of code can, of course, be arbitrarily conceived and designated at will by the programmer. Plus, reasons/motivations for changing a piece of code may be as multi-faceted as humans are. But what Uncle Bob meant was "business reason".

The SRP was conceived in an enterprise business context where multiple teams have to coordinate work, and it's important that they can work independently most of the time, within their various business subunits (teams/departments etc.). So they don't step on each others toes too much (which also explains SOLID's infatuation with interfaces..), and so that changing code to meet a business request (a business use case, or a typical request from a business department) can be localised and cohesive, making a targeted and isolated change to the code without touching common/global code.

In summary: SRP means that code should have "one business reason" to change, and have "a single business responsibility".

This is evident from the original source, where Robert C. Martin aka "Uncle Bob" writes (where brackets and emphasis are mine):

Gather together those things that change for the same reason, and separate those things that change for different reasons.

This principle is often known as the single responsibility principle, or SRP. In short, it says that a subsystem, module, class, or even a function, should not have more than one reason to change.

This principle is often known as the single responsibility principle, or SRP. In short, it says that a subsystem, module, class, or even a function, should not have more than one reason to change. The classic example is a class that has methods that deal with business rules, reports, and databases:

public class Employee {
    public Money calculatePay() ...
    public String reportHours() ...
    public void save() ...
}

Some programmers might think that putting these three functions together in the same class is perfectly appropriate. After all, classes are supposed to be collections of functions that operate on common variables. However, the problem is that the three functions change for entirely different reasons. The calculatePay function will change whenever the business rules for calculating pay do. The reportHours function will change whenever someone wants a different format for the report. The save function will change whenever the DBAs [Database Administrators] change the database schema. These three reasons to change combine to make Employee very volatile. It will change for any of those reasons.

Source: Chapter 76. The Single Responsibility Principle (from the book: "97 Things Every Programmer Should Know")

Why was it important to separate these two responsibilities into separate classes? Because each responsibility is an axis of change. When the requirements change, that change will be manifest through a change in responsibility amongst the classes. If a class assumes more than one responsibility, then there will be more than one reason for it to change. If a class has more then one responsibility, then the responsibilities become coupled. Changes to one responsibility may impair or inhibit the class’ ability to meet the others. This kind of coupling leads to fragile designs that break in unexpected ways when changed.

Source: Chapter 9 - Single Responsibility Principle

Much misunderstanding would have been averted if Uncle Bob instead of writing "reasons" had written "business reasons", which was only made clearer when one reads and interprets the fine print later on. Or if people went to the original source of SOLID and read it thoroughly, instead of going by some hearsay version of it online.

SOLID criticisms:

SOLID defense:

Related to the Single-Responsibility Principle (SRP):

  • connascence.io and Connascence at wikipedia: "In software engineering, two components are connascent if a change in one would require the other to be modified in order to maintain the overall correctness of the system." and "Components that are "born" together will often need to change together over time. Excessive connascence in our software means that the system is hard to change and hard to maintain." from Jim Weirich's youtube talk

PS: SRP can be compared with its closely related sibling, BoundedContext, which has perhaps best been defined as "A specific responsibility enforced by explicit boundaries" by Sam Newman, at 12:38. A lot of these principles are just derivations/restatements of the over-arching important software principle Prefer Cohesion over Coupling. Uncle Bob even introduces SRP by saying: "This principle was described in the work of Tom DeMarco and Meilir Page-Jones. They called it cohesion. As we’ll see in Chapter 21, we have a more specific definition of cohesion at the package level. However, at the class level the definition is similar."

Solution 11:[11]

SRP is a bit vague term in my view. No one clearly can define what a responsibility supposed to be. The way I implement it s that I strictly keep my method size below 40 and target below 15.

Try to follow common sense and don't be over obsessed with it. Try keep classes below 500 lines and methods below 30 lines at max. That will allow it to fit to a single page. Once this becomes your habit you will notice how easy it's to scale your codebase.

Reference: Uncle Bob Martin in Clean Code

Solution 12:[12]

S.O.L.I.D stands for:

  • Single responsibility Principle
  • Open-closed Principle
  • Liskov's substitution Principle
  • Interface segregation Principle
  • Dependency inversion Principle

These are the standards we refer to, when we talk about OOP. However, none of those principles can be fulfilled perfectly in software development.

You can view a very well explaining presentation about this topic here http://www.slideshare.net/jonkruger/advanced-objectorientedsolid-principles

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Steven Sudit
Solution 3
Solution 4 STW
Solution 5 Dan Bryant
Solution 6 wsanville
Solution 7 JonoW
Solution 8
Solution 9 ima
Solution 10
Solution 11
Solution 12