What is SRP and how is it used?

Asked

Viewed 1,255 times

40

I know what SRP means Principle of Single Liability. Each class must be responsible for such a thing.

  • What should I do to detect that I am violating the SRP?

  • What I must take into account to apply it correctly (use sparingly)?

A doubt as an example:

I’m developing the framework. In the part concerning the view, always consider these factors:

  • loads a file for view;
  • load the view data;
  • possibility to extend this view;
  • possibility to create blocks for the view;

In each of these cases, I must worry about creating a class that does what is intended (View, ViewBlocks, ViewData, ViewTemplate), or "play all" in class View.

If you consider "throwing it all" in the class View, would be violating the SRP?

  • 4

    I’m just not going to put another bounty on it because there’s an answer from me and I don’t think it would do any good, I don’t know why that one didn’t pan out. It’s something very important and general, has all the requirements to be one of those popular.

3 answers

28


Introducing

He is a principle to be followed and not a project pattern. So it already shows that it is difficult to define a line where they are being used correctly or not. My experience indicates that only qualified experience (and not just quantified) helps to develop the ability to define this line.

The qualification has to do with the number and types of projects that developed, the people who were participating, their dynamics, the individual attitude of the person in relation to the learning and evolution of their knowledge. And of course the ability to understand problems and abstraction is important as well. No use decorating how to use tools or how to code. You have to be able to interpret problems which is something more difficult than interpreting texts and which is somewhat deficient in most people. It is not enough to know how to use the tool you have to know what to do with it. And this is not taught in books.

Definition

The principle indicates that an application component should be responsible for only one task. Having only one feature. It has to do with cohesion.

Some people consider that this is related to OOP, but it is something general and that has been applied for decades. There was a lower use in the past because its application hindered a little the performance, what was very important at the time, today it does not weigh more and it is often possible to optimize to neither have the slightest influence that this principle causes when it breaks everything in smaller parts.

How to use it

The secret is to define what is unique functionality. If you exaggerate you will have a function running an instruction of your code more or less equivalent to a processor instruction, because this is the most unique responsibility. If you do not apply the principle you can have a "linguistics" that does several things.

Well, of course the last case only people who know nothing about it or very stubborn write something like that (we’ve already had a question here with a function of 35 thousand lines). It’s common for them to have trouble seeing all they could.

This can be easily noticed here on Sopt in the codes people post. In general the person cannot structure what is a class and what should be the methods and functions, and even worse, what should be in each one. It is even difficult to provide the best encapsulation and other techniques that help the good design of the application.

But we must think on an architectural level as well, not only of code.

When the person discovers the principle and finds it sensational he dazzles and starts to break into many small parts too.

The need for future change determines much that must be broken. And, in most situations, it is not easy to define this in advance. Unless the programmer already has previous experience with exactly the same problem. Not mastering the domain (Pun Unintended ?!? : ) ) is a requirement to achieve SRP in its fullness. What is rare happens.

The principle has much to do with the administration of change. If it were possible to make software that you never need to change (even during initial development) you would not need SRP. But it virtually doesn’t exist (scripts simple are exceptions). We are talking about maintainability. A change should have to change only one component of the application. The more granular what is the smaller change should be this component.

Arbitrarily putting things together hurts SRP? It hurts, but it doesn’t always cause problems. It happens a lot in classes whose members are all static. Of course, the ideal is not to have such arbitrary grouping, but it’s stupid to think that you can’t have all the major mathematical functions together in a class called Math. Believe some people think this because they memorize the rule and don’t look at the context and practicality. So we conclude that decide the granularity is subjective.

Other principles that help

This has to do with DRY also. If you break the pieces well it is easier to do DRY. Imagine how difficult it is to have information (a data structure, an algorithm) canonical when she carries more than she should. Imagine what would happen if you had to change it somewhere and it causes a widespread problem because part of what you had with it no longer matches the change made in one part. Without adopting SRP the DRY is impaired. And this is the most important principle to facilitate maintenance (in my opinion).

How much flexibility do you need? Let’s assume you have a tax calculation that there are several steps to perform. Does each step need to be in a different method? In a different class? It depends on the problem. If you apply the principle blindly, you incur the problem described in YAGNI. You need to see if there is a real need for each step to be changed independently.

But that’s not always a good criterion. MVC is something that reduces responsibility and increases the effort to maintain (most changes in a model must require at least one change in vision). There to avoid this problem you have to think about other forms of development not so obvious to most people. Others even know how to solve because they learned some cake recipe.

Fragmentation can get in the way of not only having to change in more than one place, but also having things spread too much. Of course there are techniques where you can fragment to have everything granular when you need it and additionally you can create "combos" ready to have things more ready to hand when it is needed.

Obviously components that join things together to facilitate common use may violate the SRP. And if it is not necessary it is bad.

Studying other principles such as those cited here helps. Another that helps is the SOLID (yes the SRP is inside it, but the other points help organize this way). Only use without exaggerations.

Never forget the YAGNI and the KISS. Study code Smells, anti-patterns.

Techniques that help

Give good names for what you’re doing help much to adopt the SRP correctly. Most people have difficulty with this. If the name is correct, it indicates what to do. But often we can only give good names when we know what it does, which makes it a paradox :)

There are only two difficult things in computing: cache invalidation and naming things.

-- Phil Karlton

If it is difficult to give a name it is because you must do more than one thing. Rethink!

Looking at the size of things helps nothing. This is a common misconception. What has to be great can be great as long as there is a reason to be so. Look at the widgets of a GUI, are monstrous.

Collecting requirements properly is another task that people do not master well. And it is critical. If you do not know ask the right questions, interpret the answers, fill in the gaps of information that you cannot get through the laymen of computing and put it all together in an organized way can’t architect the application, can’t define good names, can’t do SRP at the right level.

So I’m going to repeat that learn to code is the tip of iceberg. Developing software is solving problems, not coding. So this activity is considered by many as engineering or architecture. It’s a bit science, a little art. Or how some like it, it’s like gardening or gastronomy. We can’t even define what it is :)

Example of the question

The answers to the example cited in the question can only be given with a thorough analysis of the specific case, with all the requirements well collected. That only the AP has. Obviously ask code review in specific cases can help gain experience.

Questions that may help:

  • The break will make the most reusable code in various circumstances without causing side effects?
  • It will be easier to read the code and understand what it does?
  • Code can be easily extended?
  • He is being represented canonically?
  • Can be tested independently?
  • The information contained therein is directly related?
  • Some are too related and together are part of another entity?
  • Will it be intuitive to use this way within the requirements? How will it be used?
  • Will it be used in how many places? This can be guaranteed?

Examples

The MVC pattern is an example inductive path of SRP. He tries to make it clear which data model will be used (M), how to present this data (V) and how to operationalize it (C). Before it was common to have a single component that did all this and it was difficult to change one of the parts.

But to demonstrate how controversial what is SRP and what is not, MVC seemed to break the parts very well on this architectural level. But some people disagreed and created not only other similar models but also models that broke into more parts, for example the MVVM.

It is true that presentation and model should not be together, but most of the applications we see around are like this, and often end up working.

The most obvious example of abuse would be to create a function where it sums up two numbers. There is something ready that does this.

But that doesn’t mean I should never do this. For example: if the function does not declare that it is a sum and this is just an implementation detail, then ok. It may be that one day is not a simple sum more, or the types may change, that is, the details change despite the API remain the same.

Another example where you use something very simple would be a method that just takes one field of the class. Often the name of the method is longer than calling the field itself. It seems an exaggeration, right? It depends. Whether the method creates a better abstraction may be interesting. That is, it goes that further ahead is another field to return or that the field needs to be manipulated before returning. Breaking very simple things provides better abstraction and better documentation than that. Giving names for certain actions helps much code readability.

Business rules must go together with the persistence of the data? They are two different things. It seems obvious that they must, right? Yeah, but a lot of people don’t do that and get along very well. It decreases complexity. Of course it doesn’t apply to all cases. Then we begin to question whether all the rules should be together. Or is it just those that relate two or more parts of the entity? Or should they be grouped by some criterion? Difficult to say.

Note that the fact that a class does both is not bad in itself. It may be bad that the implementation of everything is within this class. Knowing what is abstract and what is concrete helps define responsibility. We often forget that. An interface has an abstract responsibility. And almost always people get it right :) So it seems that concrete is more complicated to define.

Separating mechanism and business rules is important, but how much? What price will you pay for it? Which parts to separate? Where to dock them?

Completion

The fact is that in any design there will be people who will say that it must be done one way and others that it must be done another way. It is something "almost arbitrary". With some criteria, of course, but it’s still something that everyone has their own way of doing. And explanations in specific and concrete cases can convince someone whether it’s right or not.

References

Wikipedia. I don’t like the article much, it is limiting and follows a source, marketeer.

Term that should also be studied together.

Study on the subject.

Alternative view to Uncle Bob’s definition that really is a little rough.

  • 1

    In short, one should know what one wants to make it work. It was a really good approach, although long, as one would expect.

  • 3

    If it is not long (and I think it will be more :) ) it does not answer anything. It only rains in the wet. Still q I find q the answer tb does a little this. At least p/ who already understands some of this. Short answer is good for followers of recipes. But in this case there is no recipe. This is where you differentiate the chef from the chef.

  • 2

    Based on that part you added, more than truth couldn’t be, this convincing people that one, and only one way is right. A simple solution to this, is to know the different implementations, so as to create an own opinion.

13

What is SRP?

The Single Responsibility Principle ("SRP" or "Principle of Single Liability"), determines that each component of the system shall have only one responsibility.

Bringing to Object Orientation (since you spoke in class), we say that each class or object must have a single responsibility.

What should I do to detect that I am violating the SRP?

If a class has a single responsibility, it has a single reason to change.

If you need to tinker with a class for a variety of reasons (for example in this type of "utility class"), you are violating the principle.

Let’s say for example that you do not separate the concepts from your system, and make rules of business, presentation, interface and persistence in the same class, then:

  • When the size of a field changes, you touch this class.
  • When the name of a database column changes, you move this class.
  • When a business calculation changes, you touch this class.
  • When another business calculation changes, you touch this same class.

Now, this class has far more than one reason to change, so she’s violating the SRP.

What I must take into account to apply it correctly?

The hardest part is identifying what is a single responsibility.

If I make an entire inventory control system in a single class and someone asks me what is the responsibility of this class, I’ll say: "the responsibility of this class is to control the stock, and changes in stock control is the only reason that can require class change", and it can be hard to prove me wrong.

To identify if a class has more than one reason to change we can observe the mechanics of solving the problem: the workflow, activities or tasks and entities involved.

In this my first example it is easy: to control the stock I need to do inventory, record input and output of products, record losses, issue reports, print documents, etc.

If a single class has all these responsibilities, it will need to change for example when there is a requirement change in the inventory and also when there is a requirement change in the output of products - it seems quite clear that there are two distinct reasons for change.

But SRP is more useful if it is also respected at a much lower level.

For example, once I needed to make a component to export to text file a message received from a message queue; this message came in the form of an object.

Exporting an object to file is a single responsibility? It seems so, so I started drawing the class:

inserir a descrição da imagem aqui

When I started writing the export, I noticed that there were two tasks involved: formatting the attributes in the text and saving this text to file, and decided to separate these tasks into separate classes:

inserir a descrição da imagem aqui

Now I had a specialized class on each task, and another class coordinating the work, and delivered the solution.

Shortly after, came the requirement to format the message slightly differently, and only the class Formatting needed to change, the other two were not touched.

Later came the requirement to have one more formatting option, keeping active also the previous formatting (would be used now one formatting and sometimes another). So I created one more formatting class and just the Exportarmensagem needed to be changed to choose the formatter as per the occasion; the other two classes were not played.

inserir a descrição da imagem aqui

Believe it or not, then came the need to instead of simply saving to file the formatted text, the file should also be sent through the network using a specialized application; and then only the class Exportararquivo needed to be changed, the other classes were not touched.

Until the end of this story, each of the classes involved in exporting the message had only one reason to change, which gives each one the SRP :D compliance medal

Of course this medal can be revoked at any time.

To play everything in the same class would be to violate the SRP?

Yes, of course.

If you have realized more than one responsibility and yet implemented everything in the same class, you deliberately violated the SRP.

The point is: when violating the SRP is a problem?

As I said at the beginning, a class violates the SRP when it has more than one reason to change.

And if class, even if it has more than one responsibility, never needs to change?

So you’ve committed no sin and maybe saved yourself the trouble.

In my example of the message exporter, if I had started with a single class and waited until the first change of requirement to break the classes, provided that this single class was well written, I believe I would have been fine.

Completion

We don’t separate responsibilities just because it’s beautiful or because we’re expecting certain changes.

We separate responsibilities because, due to the characteristics of the project, we know that the changes will inevitably come (never the expected changes, always others) and we prefer to have a design that facilitates implementing these changes.

6

(Part translation of this answer - accept feedback on translation).

Principle of Single Liability

Throw away whatever you believe that this principle means.

Robert C. Martin officially defines this principle as:

A class must have only one reason to change

Most people defining SRP are mistaken. SRP is typically poorly explained as:

"The class Empregado must not have AtualizarDadosDemograficos() and EnviarMensagem(), this counts as two responsibilities... place EnviarMensagem() in a class Mensagem!!"

^^ Wrong

vv Certo

Robert C. Martin said

"A responsibility is not 'something the code does'". (NDC [Norwegian Developers Conference] 2012)

Robert C. Martin defines SRP as:

"Any module should be responsible for with only a person-[paper]." (NDC 2012)

When a Stakeholder asks for a change in data ordering in the View, management should not be scared and worried that it might break the algorithms. This is because The module dealing with Ordering in the View only owes responsibility to the interested party, and The module dealing with the calculation algorithm of the total only owes responsibility to the business analyst. So when the Business Analyst asks you to change the algorithm, we should not fear that the View might change.

Therefore, any change in A module (natural) only occurs for one reason: the Single Person-Paper who this module serves requested a change.

(N.T.: Where one perceives that in Portuguese there is a translation problem, in which the focus of the word responsibility should not be "what is the responsibility" [responsible for] but "to whom one owes responsibility" [responsibility]).

Support this definition:

Robert C. Martin - "Who is the program?"

"[There is a general] confusion [on the subject]" - answer to the question "What is the real Responsibility of a class?"

Answer to the question "How do you determine how Oarse or fine-grained a 'Responsibility' should be when using the single Responsibility principle?"

Answer to the question "Clarify the Single Responsibility Principle"

Here also deals with the issue of English.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.