Core Java

SRP is a Hoax

The Single Responsibility Principle, according to Robert Martin‘s Clean Code, means that “a class should have only one reason to change.” Let’s try to decrypt this rather vague statement and see how it helps us design better object-oriented software. If it does.

The Thomas Crown Affair (1999) by John McTiernan

I mentioned SRP once in my post about SOLID, saying that it doesn’t really help programmers understand the good old “high cohesion” concept, which was introduced by Larry Constantine back in 1974. Now let’s see it by example and analyze how we can improve a class, with the SRP in mind, and whether it will become more object-oriented.

Let’s try the class AwsOcket from jcabi-s3 (I’ve simplified the code):

class AwsOcket {
  boolean exists() { /* ... */ }
  void read(final OutputStream output) { /* ... */ }
  void write(final InputStream input) { /* ... */ }
}

Correct me if I’m wrong, but according to SRP this class is responsible for too many things: 1) checking the existence of an object in AWS S3, 2) reading its content, and 3) modifying its content. Right? It’s not a good design and it must be changed.

In order to change it and make it responsible for just one thing we must introduce a getter, which will return an AWS client and then create three new classes: ExistenceChecker, ContentReader, and ContentWriter. They will check, read, and write. Now, in order to read the content and print it to the console I’m currently doing this:

if (ocket.exists()) {
  ocket.read(System.out);
}

Tomorrow, if I refactor the class, I will be doing this:

if (new ExistenceChecker(ocket.aws()).exists()) {
  new ContentReader(ocket.aws()).read(System.out);
}

Aside from the fact that these checkers, readers, and writers are not really classes, but pure holders of procedures, the usage of this ocket turns into a nightmare. We can’t really know anymore what will happen with it when we pass it somewhere. We can’t, for example, guarantee that the content that is coming from it is decrypted or decoded on the fly. We simply can’t decorate it. It is not an object anymore, but a holder of an AWS client, which is used by some other classes somewhere.

Yes, now it is responsible for only one thing: encapsulating the reference to the AWS client. It is a perfect class as far as SRP is concerned. But it is not an object anymore.

The same will happen with any class if you apply the SRP principle to its full extent: it will become a holder of data or of other objects, with a collection of setters and getters on top of them. Maybe with one extra method in addition to those.

My point is that SRP is a wrong idea.

Making classes small and cohesive is a good idea, but making them responsible “for one thing” is a misleading simplification of a “high cohesion” concept. It only turns them into dumb carriers of something else, instead of being encapsulators and decorators of smaller entities, to construct bigger ones.

In our fight for this fake SRP idea we lose a much more important principle, which really is about true object-oriented programming and thinking: encapsulation. It is much less important how many things an object is responsible for than how tightly it protects the entities it encapsulates. A monster object with a hundred methods is much less of a problem than a DTO with five pairs of getters and setters! This is because a DTO spreads the problem all over the code, where we can’t even find it, while the monster object is always right in front of us and we can always refactor it into smaller pieces.

Encapsulation comes first, size goes next, if ever.

Published on Java Code Geeks with permission by Yegor Bugayenko, partner at our JCG program. See the original article here: SRP is a Hoax

Opinions expressed by Java Code Geeks contributors are their own.

Yegor Bugayenko

Yegor Bugayenko is an Oracle certified Java architect, CEO of Zerocracy, author of Elegant Objects book series about object-oriented programing, lead architect and founder of Cactoos, Takes, Rultor and Jcabi, and a big fan of test automation.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

2 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Thai H
Thai H
6 years ago

I still believe in SRP. I guess your problem is it was not applied appropriately. The main purpose of the code design is to make it easier to maintain (to survive in the ever changing world). So designs must be practical (and not trying to be ideal/purist as in textbooks). There are many examples for this (like AWT/SWT, Smalltalk/C++, ..) So to answer the question (what should be my code “units”?) we need to understand the requirements. In your case, because you just want to use AwsOcket to do simple read/write then it should be your “unit”. But in other… Read more »

Jarrod Roberson
Jarrod Roberson
6 years ago

I think your definition of “One Thing” is not the same as Robert Martin’s or for that matter most other peoples definition based on what he wrote.

I believe the intention of that statement is the “one thing” is kind of a judgement call. As is, the AwsOcket class is handing just “one thing”, and Ocket, whatever that is. Your interpretation is “one behavior”, which is an incorrect interpretation and kind of makes this entire rant/post irrelevant because it is based on a fundamentally flawed premise.

Back to top button