For example, there is a repository class that goes to the REST API, receives JSON and parses it into the necessary structure, then puts the data into the cache (let it be SQLite). In fact, I have one method in the repository, for example:

Message[] getMessages(int offset, int count) 

So, it seems like one duty, but how to perceive the fact that in the implementation of this method a class can go to Http, Knows about the data format and knows how to parse Json, and also knows that there is a cache with different rules for each method and you need to put something in it.

What to do with such methods? Even if I hide access to Http and parsing with the cache for additional abstractions, it will not hide the fact that the repository still knows about the method of obtaining that the received data should be parsed and cached. In fact, I will have to touch the repository if access to data changes, for example, from Http, to Sqlite, if the data format changes from json to xml, or to Cursor from Sqlite, or I need to cut the cache.

Is the SRP principle broken or not here?

  • one
    depending on how it is implemented. If you create the cache and save it yourself, it is most likely broken, but if all the work with the cache is reduced to transferring data to some object, then most likely it is not broken. We need to look at it this way: if you need to change the cache from one to another - will the class (or its parents) have to be changed? If it is necessary, then the principle is violated, if it is not necessary (i.e., the cache is received from somewhere outside), then it is not violated. In this case, the factory method should not be considered a violation of this principle - BOPOH
  • If you are given an exhaustive answer, mark it as correct (tick the selected answer). - andreycha

2 answers 2

The SRP interface does not break. Implementation - violates. It is necessary to hide responsibility for abstractions.

As far as I understand, this point is the main difficulty for you:

Even if I hide access to Http and parsing with the cache for additional abstractions, it will not hide the fact that the repository still knows about the method of obtaining that the received data should be parsed and cached.

There is no problem that the class knows what to do. The only problem is that he does it himself. If you hide different stages behind abstractions, these responsibilities will go from class to abstraction.

  • Those. class duties include working with cache, Http and Json. How do they work the class in a drum, everything is fine. But, embarrassed by the fact that if Json is replaced by Xml, the changes will affect the class of the repository. Or if we change Http to Sqlite, another change will affect the class of the repository. - Alexey Malchenko
  • If you hide different stages behind abstractions - is it said here about parents? So if we need to change work with the same cache? Changing the parent is bad, then you have to change the current class, and then everything hidden will come out? Then why is this not a violation? - BOPOH
  • @ Alexey Malchenko make abstractions so that you do not have to change the class of the repository when changing the format. - Pavel Mayorov
  • @ Alexey Malchenko then they are abstractions. - Pavel Mayorov
  • one
    @ Alexey Malchenko in this case, you rewrite the repository, and throw the old abstractions into the furnace. Do not try to "pull" the abstraction for the wrong application. - Pavel Mayorov

It is better to break it into several classes:

  • if you need to change one thing, you will have to check if something else is broken.
  • It is very difficult to write tests: it is necessary either to write a lot of code, or to test few boundary options
  • classes for working with cache, downloading and parsing data from other services may be useful for other tasks

Regarding the SRP, Robert Martin said: "A class should have only one reason to change."
In principle, we can say that this is one reason, but, to be frank with you, it is clear that this is not so. I usually ask the question: "If we take out this logic separately, will it be easier to write the tests correctly?"