{"id":34828,"date":"2019-10-31T22:00:38","date_gmt":"2019-10-31T19:00:38","guid":{"rendered":"https:\/\/prohoster.info\/blog\/single-responsibility-principle-ne-takoj-prostoj-kak-kazhetsya\/"},"modified":"2019-10-31T22:00:38","modified_gmt":"2019-10-31T19:00:38","slug":"single-responsibility-principle-ne-takoj-prostoj-kak-kazhetsya","status":"publish","type":"post","link":"https:\/\/prohoster.info\/en\/blog\/news\/single-responsibility-principle-ne-takoj-prostoj-kak-kazhetsya","title":{"rendered":"Single Responsibility Principle. Not as simple as it seems","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Single Responsibility Principle. Not as simple as it seems\" src=\"\/wp-content\/uploads\/2019\/06\/5b253ff55e3c97b6baf5f7a7ae7f3b98.JPG\" style=\"display:block;margin: 0 auto;\" \/> Single Responsibility Principle, also known as the principle of single responsibility,<br \/>\nis a concept that can be quite slippery to grasp and is a rather nerve-wracking question in programmer interviews. <\/p>\n<p><\/p>\n<p>My first serious encounter with this principle occurred at the beginning of my first year, when a group of us young and inexperienced students was taken to the woods to turn us from caterpillars into real students.<\/p>\n<p><\/p>\n<p>In the woods, we were divided into groups of 8-9 people each and set up a competition \u2014 which group could finish a bottle of vodka the fastest, provided that the first person in the group pours the vodka into a glass, the second drinks it, and the third has a bite to eat. The unit performing its task then moves to the back of the queue. <\/p>\n<p><\/p>\n<p>A case where the size of the queue was a multiple of three was a good implementation of SRP.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex> <\/p>\n<h2 id=\"opredelenie-1-edinaya-otvetstvennost\">Definition 1. Single Responsibility.<\/h2>\n<p><\/p>\n<p>The official definition of the Single Responsibility Principle (SRP) states that each object has its own responsibility and reason for existence, and that responsibility is singular.<\/p>\n<p><\/p>\n<p>Let's consider the object \"Drinker\" (<strong>Tippler<\/strong>).<br \/>\nTo implement the SRP, we can divide the responsibilities among three individuals: <\/p>\n<p><\/p>\n<ul>\n<li>One pours (<strong>PourOperation<\/strong>)<\/li>\n<li>One drinks (<strong>DrinkUpOperation<\/strong>)<\/li>\n<li>One has a bite (<strong>TakeBiteOperation<\/strong>)<\/li>\n<\/ul>\n<p><\/p>\n<p>Each participant in the process is responsible for one component of the process, meaning they have one atomic responsibility \u2014 to drink, pour, or have a bite. <\/p>\n<p><\/p>\n<p>The Tippler, in turn, serves as a facade for these operations:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">class Tippler {\n    \/\/...\n    void Act(){\n        _pourOperation.Do() \/\/ pour\n        _drinkUpOperation.Do() \/\/ drink\n        _takeBiteOperation.Do() \/\/ have a bite\n    }\n}<\/code><\/pre>\n<p>\n<img decoding=\"async\" alt=\"Single Responsibility Principle. Not as simple as it seems\" src=\"\/wp-content\/uploads\/2019\/06\/8d591a474e3555edfee3ffebc28d079b.JPG\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<h4 id=\"zachem\">Why?<\/h4>\n<p><\/p>\n<p>The programmer writes code for the monkey, and the monkey is inattentive, foolish, and always in a hurry. It can retain and understand about 3 to 7 terms at one time.<br \/>\nIn the case of the Tippler, these terms are three. However, if we write code in one long block, it will contain hands, glasses, fights, and endless arguments about politics. And all this will be in the body of a single method. I'm sure you've seen such code in your practice. Not the most humane test for the psyche.<\/p>\n<p><\/p>\n<p>On the other hand, the ape-man is focused on modeling real-world objects in his mind. In his imagination, he can collide them, assemble new objects from them, and likewise disassemble them. Imagine an old car model. You can imagine opening the door, unscrewing the door trim, and seeing the mechanisms of the power windows, inside which will be gears. But you can't see all the components of the car at once, in one \"listing\". At least the \"ape-man\" can't.<\/p>\n<p><\/p>\n<p>Therefore, programmer-people decompose complex mechanisms into a set of less complex and functional elements. However, decomposition can be done in different ways: in many old cars, the air duct goes into the door, while in modern ones, a failure of the lock electronics prevents the engine from starting, which complicates repairs.<\/p>\n<p><\/p>\n<p>So, <strong>SRP is a principle that explains HOW to decompose, meaning where to draw the line of separation.<\/strong>. <\/p>\n<p><\/p>\n<p>He says that decomposition should follow the principle of 'separation of responsibility', that is, by the tasks of various objects.<\/p>\n<p>\n<img decoding=\"async\" alt=\"Single Responsibility Principle. Not as simple as it seems\" src=\"\/wp-content\/uploads\/2019\/06\/b1980c3dc9742b921eb818f14fe3527e.JPG\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Let's return to the drinker and the benefits that the man-ape gets from decomposition: <\/p>\n<p><\/p>\n<ul>\n<li>The code has become extremely clear at every level.<\/li>\n<li>Code can be written by several programmers simultaneously (each writes a separate element).<\/li>\n<li>Automated testing is simplified\u2014the simpler the element, the easier it is to test.<\/li>\n<li>There is composability of code\u2014you can replace <strong>DrinkUpOperation<\/strong> with an operation where the drinker pours liquid under the table. Or replace the pouring operation with an operation where you mix wine and water or vodka and beer. Depending on the business requirements, you can do everything, while not touching the method's code. <strong>Tippler.Act<\/strong>. <\/li>\n<li>From these operations, you can build a glutton (using only <strong>TakeBitOperation<\/strong>), an Alcoholic (using only <strong>DrinkUpOperation<\/strong> directly from the bottle), and satisfy many other business requirements.<\/li>\n<\/ul>\n<p><\/p>\n<p><em>(Oh, it seems this is already the OCP principle, and I broke the responsibility of this post.) <\/em><\/p>\n<p><\/p>\n<p>And, of course, the downsides: <\/p>\n<p><\/p>\n<ul>\n<li>You will have to create more types. <\/li>\n<li>The drinker will first drink a couple of hours later than he could have.<\/li>\n<\/ul>\n<p><\/p>\n<h2 id=\"opredelenie-2-edinaya-izmenchivost\">Definition 2. Single variability.<\/h2>\n<p><\/p>\n<p>Hold on, gentlemen! The class of drinkers also performs a unified responsibility \u2014 it drinks! And in general, the word 'responsibility' is a very vague concept. Someone is responsible for the fate of humanity, while someone else is responsible for picking up penguins that have fallen on the pole.<\/p>\n<p><\/p>\n<p>Let's consider two implementations of the drinker. The first one mentioned above includes three classes \u2014 pour, drink, and snack.<\/p>\n<p><\/p>\n<p>The second one is written through the methodology of 'Forward and only forward' and contains all the logic in the method. <strong>Act<\/strong>:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">\/\/\u041d\u0435 \u0442\u0440\u0430\u0442\u044c\u0442\u0435 \u0432\u0440\u0435\u043c\u044f  \u043d\u0430 \u0438\u0437\u0443\u0447\u0435\u043d\u0438\u0435 \u044d\u0442\u043e\u0433\u043e \u043a\u043b\u0430\u0441\u0441\u0430. \u041b\u0443\u0447\u0448\u0435 \u0441\u044a\u0435\u0448\u044c\u0442\u0435 \u043f\u0435\u0447\u0435\u043d\u044c\u043a\u0443\n\u0441lass BrutTippler {\n   \/\/...\n   void Act(){\n        \/\/ \u043d\u0430\u043b\u0438\u0432\u0430\u0435\u043c\n    if(!_hand.TryDischarge(from:_bottle, to:_glass, size:_glass.Capacity))\n        throw new OverdrunkException();\n\n    \/\/ \u0432\u044b\u043f\u0438\u0432\u0430\u0435\u043c\n    if(!_hand.TryDrink(from: _glass,  size: _glass.Capacity))\n        throw new OverdrunkException();\n\n    \/\/\u0417\u0430\u043a\u0443\u0441\u044b\u0432\u0430\u0435\u043c\n    for(int i = 0; i&lt; 3; i++){\n        var food = _foodStore.TakeOrDefault();\n        if(food==null)\n            throw new FoodIsOverException();\n\n        _hand.TryEat(food);\n    }\n   }\n}<\/code><\/pre>\n<p><\/p>\n<p>Both of these classes, from the perspective of an outside observer, look absolutely the same and perform the unified responsibility of 'drinking'. <\/p>\n<p><\/p>\n<p>Awkward!<\/p>\n<p><\/p>\n<p>Then we go online and learn another definition of SRP \u2014 Single Responsibility Principle.<\/p>\n<p><\/p>\n<p>SCP states that '<strong>A module has one and only one reason to change<\/strong>' That is, 'Responsibility is a reason for change'. <\/p>\n<p><\/p>\n<p><em>(It seems that the guys who came up with the original definition were confident in the telepathic abilities of a human-ape)<\/em><\/p>\n<p><\/p>\n<p>Now everything falls into place. Procedures for pouring, drinking, and snacking can be changed separately, while in the drinker, we can only change the sequence and composition of operations, for example, by moving the snack before drinking or adding reading a toast.<\/p>\n<p><\/p>\n<p>In the 'Forward and only forward' approach, everything that can be changed is changed only in the method. <strong>Act<\/strong>. This can be readable and effective when there is little logic and it rarely changes, but often it ends with terrible methods of 500 lines each, with the number of if-statements exceeding what is required for Russia's entry into NATO. <\/p>\n<p><\/p>\n<h2 id=\"opredelenie-3-lokalizaciya-izmeneniy\">Definition 3. Localization of changes.<\/h2>\n<p><\/p>\n<p>Drinkers often don't understand why they woke up in someone else's apartment, or where their mobile phone is. It's time to add detailed logging.<\/p>\n<p><\/p>\n<p>Let's start logging the pouring process:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">class PourOperation: IOperation{\n    PourOperation(ILogger log \/*....*\/){\/*...*\/}\n    \/\/...\n    void Do(){\n        _log.Log($\"Before pour with {_hand} and {_bottle}\");\n        \/\/Pour business logic ...\n        _log.Log($\"After pour with {_hand} and {_bottle}\");\n    }\n}<\/code><\/pre>\n<p><\/p>\n<p>Encapsulating it in <strong>PourOperation<\/strong>, we acted wisely in terms of responsibility and encapsulation, but now we face a dilemma with the principle of changeability. Besides the operation itself, which may change, the logging process is also becoming variable. We'll need to separate it and create a special logger for the pouring operation:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">interface IPourLogger{\n    void LogBefore(IHand, IBottle){}\n    void LogAfter(IHand, IBottle){}\n    void OnError(IHand, IBottle, Exception){}\n}\n\nclass PourOperation: IOperation{\n    PourOperation(IPourLogger log \/*....*\/){\/*...*\/}\n    \/\/...\n    void Do(){\n        _log.LogBefore(_hand, _bottle);\n        try{\n             \/\/... business logic\n             _log.LogAfter(_hand, _bottle);\n        }\n        catch(exception e){\n            _log.OnError(_hand, _bottle, e);\n        }\n    }\n}<\/code><\/pre>\n<p><\/p>\n<p>A meticulous reader will notice that <strong>LogAfter<\/strong>, <strong>LogBefore<\/strong> and <strong>OnError<\/strong> can also change separately, and similarly to the previous actions, it will create three classes: <strong>PourLoggerBefore<\/strong>, <strong>PourLoggerAfter<\/strong> and <strong>PourErrorLogger<\/strong>.<\/p>\n<p><\/p>\n<p>And recalling that there are three operations for the pouring action, we end up with nine logging classes. Ultimately, the entire pouring operation consists of 14 (!!!) classes.<\/p>\n<p><\/p>\n<p>Hyperbole? Hardly! A person with a decompositional grenade will break the 'pourer' down into a decanter, a glass, pouring operators, a water service, a physical model of molecular collision, and in the next quarter he will be trying to untangle dependencies without global variables. And believe me \u2014 he won't stop.<\/p>\n<p><\/p>\n<p>It is precisely at this moment that many come to the conclusion that SRP is a fairy tale from pink kingdoms, and go off to spin noodles\u2026<\/p>\n<p><\/p>\n<p>\u2026 without ever learning of the existence of the third definition of SRP: <\/p>\n<p><\/p>\n<p>'The Single Responsibility Principle states that <strong>similar things that need to change should be kept in one place<\/strong>' or '<strong>What changes together should be stored in one place.<\/strong>\u201d<\/p>\n<p><\/p>\n<p>In other words, if we are changing the logging of the operation, we should change it in one place.<\/p>\n<p><\/p>\n<p>This is a very important point \u2014 as all the explanations of SRP above discussed that types should be broken down as much as possible, implying an 'upper limit' on the size of an object, and now we are talking about a 'lower limit' as well. In other words, <strong>SRP not only requires to 'break until it breaks', but also not to overdo it \u2014 'do not separate connected things'.<\/strong>It's a great battle between Occam's razor and the person with the monkey!<\/p>\n<p>\n<img decoding=\"async\" alt=\"Single Responsibility Principle. Not as simple as it seems\" src=\"\/wp-content\/uploads\/2019\/06\/2e349a5b119a511d716341f3f6725844.JPG\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>Now it should be easier for the pourer. Besides the fact that there\u2019s no need to break the IPourLogger into three classes, we can also consolidate all loggers into one type:<\/p>\n<p><\/p>\n<pre><code class=\"plaintext\">class OperationLogger{\n    public OperationLogger(string operationName){\n\/*..*\/}\n    public void LogBefore(object[] args){\n\/*...*\/}\n    public void LogAfter(object[] args){\n\/*..*\/}\n    public void LogError(object[] args, exception e){\n\/*..*\/}\n}<\/code><\/pre>\n<p><\/p>\n<p>And if we add a fourth type of operation, logging for it is already prepared. The code for the operations themselves is clean and free of infrastructural noise.<\/p>\n<p><\/p>\n<p>As a result, we have 5 classes for the task of drinking:<\/p>\n<p><\/p>\n<ul>\n<li>Pouring Operation<\/li>\n<li>Drinking Operation<\/li>\n<li>Chasing Operation<\/li>\n<li>Logger<\/li>\n<li>Drinker Facade<\/li>\n<\/ul>\n<p><\/p>\n<p>Each of them is strictly responsible for one functionality, having a single reason for change. All similar rules for modification lie close by. <\/p>\n<p>\n<b class=\"spoiler_title\">Real-Life Example<\/b><\/p>\n<p>Once we wrote a service for automatic B2B client registration. Then a GOD method appeared, containing 200 lines of similar content:<\/p>\n<p><\/p>\n<ul>\n<li>Go to 1C and create an account<\/li>\n<li>With this account, go to the payment module and set it up there<\/li>\n<li>Check that an account with this number hasn\u2019t been created in the main system <a class=\"wpil_keyword_link\" href=\"https:\/\/prohoster.info\/en\/server\/dts-dronten\/\"   title=\"server\" data-wpil-keyword-link=\"linked\"  data-wpil-monitor-id=\"2485\">server<\/a><\/li>\n<li>Create a new account<\/li>\n<li>Add the registration result from the payment module and the 1C number to the registration results service<\/li>\n<li>Add the account information to this table<\/li>\n<li>Create a point number for this client in the points service. Pass the 1C account number to this service.<\/li>\n<\/ul>\n<p><\/p>\n<p>And there were about 10 more business operations in this list with dreadful interdependencies. The account object was needed by almost everyone. The point identifier and client name were needed in half the calls.<\/p>\n<p><\/p>\n<p>After an hour of refactoring, we managed to separate the infrastructural code and some subtleties of account operations into separate methods\/classes. The God method became lighter, but 100 lines of code remained that refused to be unraveled. <\/p>\n<p><\/p>\n<p>Only after a few days did the realization come that the essence of this 'lightened' method is a business algorithm. And that the initial description of the specification was quite complex. And it is the attempt to break this method into pieces that would violate SRP, not the other way around. <\/p>\n<p><\/p>\n<h2 id=\"formalizm\">Formalism.<\/h2>\n<p><\/p>\n<p>It\u2019s time to leave our drinker behind. Wipe your tears\u2014 we will definitely return to him someday. But now let\u2019s formalize the knowledge from this article. <\/p>\n<p><\/p>\n<h4 id=\"formalizm-1-opredelenie-srp\">Formalism 1. Definition of SRP<\/h4>\n<p><\/p>\n<ol>\n<li>Separate elements so that each is responsible for something singular.<\/li>\n<li>Responsibility is defined as a \"reason for change.\" That is, each element has only one reason for change in terms of business logic.<\/li>\n<li>Potential changes in business logic must be localized. Modifiable synchronous elements should be adjacent.<\/li>\n<\/ol>\n<p><\/p>\n<h4 id=\"formalizm-2-neobhodimye-kriterii-samoproverki\">Formalism 2. Necessary self-check criteria.<\/h4>\n<p><\/p>\n<p>I have not encountered sufficient criteria for SRP compliance. However, there are essential conditions:<\/p>\n<p><\/p>\n<p>1) Ask yourself the question \u2014 what does this class\/method\/module\/service do? You should answer it with a simple definition. (thank you) <noindex><a rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/users\/brightori\/\" class=\"user_link\">Brightori<\/a><\/noindex> )<\/p>\n<p>\n<b class=\"spoiler_title\">explanations<\/b><\/p>\n<p>However, sometimes finding a simple definition is very difficult. <\/p>\n<p><\/p>\n<p>2) Fixing a certain bug or adding a new feature affects the minimum number of files\/classes. Ideally \u2014 one. <\/p>\n<p>\n<b class=\"spoiler_title\">explanations<\/b><\/p>\n<p>Since the responsibility (for the feature or bug) is encapsulated in one file\/class, you know exactly where to look and what to correct. For example: a feature to change the logging output of operations would only require changing the logger. There's no need to search through the rest of the code. <\/p>\n<p><\/p>\n<p>Another example \u2014 adding a new UI control similar to previous ones. If this forces you to add 10 different entities and 15 different converters \u2014 it seems you've 'over-engineered'.<\/p>\n<p><\/p>\n<p>3) If multiple developers are working on different features of your project, the likelihood of a merge conflict, meaning the probability that the same file\/class will be changed by multiple developers simultaneously, is minimal.<\/p>\n<p>\n<b class=\"spoiler_title\">explanations<\/b><\/p>\n<p>If adding a new operation \"Pour vodka under the table\" requires touching the logger, drinking, and pouring operations \u2014 it seems that the responsibilities are unevenly divided. Certainly, this is not always possible, but it\u2019s essential to strive to reduce this indicator. <\/p>\n<p><\/p>\n<p>4) When clarifying questions about business logic (from a developer or manager), you delve strictly into one class\/file and get information only from there.<\/p>\n<p>\n<b class=\"spoiler_title\">explanations<\/b><\/p>\n<p>Features, rules, or algorithms are compactly written, each in one place, rather than scattered as flags throughout the code space.<\/p>\n<p><\/p>\n<p>5) Naming is clear.<\/p>\n<p>\n<b class=\"spoiler_title\">explanations<\/b><\/p>\n<p>Our class or method is responsible for only one thing, and that responsibility is reflected in its name.<\/p>\n<p><\/p>\n<p>AllManagersManagerService \u2014 likely a God class.<br \/>\nLocalPayment \u2014 probably not. <\/p>\n<p><\/p>\n<h4 id=\"formalizm-3-metodika-razrabotki-okkama-first\">Formalism 3. The development methodology \"Ockham's First.\"<\/h4>\n<p><\/p>\n<p>At the beginning of design, a person-monkey does not know or feel all the subtleties of the task at hand and can make mistakes. Mistakes can happen in various ways:<\/p>\n<p><\/p>\n<ul>\n<li>Creating overly large objects by combining different responsibilities<\/li>\n<li>Break it down by dividing a single responsibility into many different types<\/li>\n<li>Incorrectly defining the boundaries of responsibility<\/li>\n<\/ul>\n<p><\/p>\n<p>It is crucial to remember the rule: \"it\u2019s better to err on the side of caution,\" or \"if unsure, do not split.\" For example, if your class encompasses two responsibilities, it remains clear and can be split into two with minimal changes to client code. However, reconstructing a glass from shards is generally more challenging due to the context being spread across multiple files and the lack of necessary dependencies in client code. <\/p>\n<p><\/p>\n<h2 id=\"pora-zakruglyatsya\">It's time to wrap up<\/h2>\n<p><\/p>\n<p>The application scope of SRP is not limited to OOP and SOLID. It applies to methods, functions, classes, modules, microservices, and services. It is applicable to both \"fine-tuning\" and \"rocket science\" development, making the world a little better everywhere. When you think about it, it\u2019s arguably a fundamental principle of all engineering. Mechanical engineering, control systems, and indeed all complex systems are built from components, and \"under-splitting\" deprives designers of flexibility, while \"over-splitting\" deprives them of efficiency, and incorrect boundaries rob them of clarity and peace of mind. <\/p>\n<p>\n<img decoding=\"async\" alt=\"Single Responsibility Principle. Not as simple as it seems\" src=\"\/wp-content\/uploads\/2019\/06\/b70fb2b0b87cf90d41462263e839902b.JPG\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p>SRP is not a natural invention and is not part of the exact sciences. It arises from our biological and psychological limitations. It is merely a way to control and develop complex systems using the brain of a human-ape. It tells us how to decompose a system. The original formulation required considerable telepathic skill, but I hope this article somewhat clears the smoke.<\/p>\n<p>Source: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/454290\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>Single responsibility principle, \u043e\u043d \u0436\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0435\u0434\u0438\u043d\u043e\u0439 \u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e\u0441\u0442\u0438, \u043e\u043d \u0436\u0435 \u043f\u0440\u0438\u043d\u0446\u0438\u043f \u0435\u0434\u0438\u043d\u043e\u0439 \u0438\u0437\u043c\u0435\u043d\u0447\u0438\u0432\u043e\u0441\u0442\u0438 \u2014 \u043a\u0440\u0430\u0439\u043d\u0435 \u0441\u043a\u043e\u043b\u044c\u0437\u043a\u0438\u0439 \u0434\u043b\u044f \u043f\u043e\u043d\u0438\u043c\u0430\u043d\u0438\u044f \u043f\u0430\u0440\u0435\u043d\u044c \u0438 \u0441\u0442\u043e\u043b\u044c \u043d\u0435\u0440\u0432\u043e\u0437\u043d\u044b\u0439 \u0432\u043e\u043f\u0440\u043e\u0441 \u043d\u0430 \u0441\u043e\u0431\u0435\u0441\u0435\u0434\u043e\u0432\u0430\u043d\u0438\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0441\u0442\u0430. \u041f\u0435\u0440\u0432\u043e\u0435 \u0441\u0435\u0440\u044c\u0435\u0437\u043d\u043e\u0435 \u0437\u043d\u0430\u043a\u043e\u043c\u0441\u0442\u0432\u043e \u0441 \u044d\u0442\u0438\u043c \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043b\u043e\u0441\u044c \u0434\u043b\u044f \u043c\u0435\u043d\u044f \u0432 \u043d\u0430\u0447\u0430\u043b\u0435 \u043f\u0435\u0440\u0432\u043e\u0433\u043e \u043a\u0443\u0440\u0441\u0430, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u043b\u043e\u0434\u044b\u0445 \u0438 \u0437\u0435\u043b\u0435\u043d\u044b\u0445 \u043d\u0430\u0441 \u0432\u044b\u0432\u0435\u0437\u043b\u0438 \u0432 \u043b\u0435\u0441, \u0447\u0442\u043e\u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0438\u0437 \u043b\u0438\u0447\u0438\u043d\u043e\u043a \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u043e\u0432 \u2014 \u0441\u0442\u0443\u0434\u0435\u043d\u0442\u043e\u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0438\u0445. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":26229,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[702],"tags":[],"class_list":["post-34828","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-news"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.2 - aioseo.com -->\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/en\/blog\/news\/single-responsibility-principle-ne-takoj-prostoj-kak-kazhetsya\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.2\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47Single Responsibility Principle. \u041d\u0435 \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043a\u0430\u043a \u043a\u0430\u0436\u0435\u0442\u0441\u044f | ProHoster\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/en\/blog\/news\/single-responsibility-principle-ne-takoj-prostoj-kak-kazhetsya\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:00:38+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:00:38+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Single Responsibility Principle. Not as simple as it seems | ProHoster","description":"","canonical_url":"https:\/\/prohoster.info\/en\/blog\/news\/single-responsibility-principle-ne-takoj-prostoj-kak-kazhetsya","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"en_US","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47Single Responsibility Principle. \u041d\u0435 \u0442\u0430\u043a\u043e\u0439 \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u043a\u0430\u043a \u043a\u0430\u0436\u0435\u0442\u0441\u044f | ProHoster","og:url":"https:\/\/prohoster.info\/en\/blog\/news\/single-responsibility-principle-ne-takoj-prostoj-kak-kazhetsya","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:00:38+00:00","article:modified_time":"2019-10-31T19:00:38+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"34828","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-02-09 21:46:19","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 02:14:06","updated":"2026-02-09 21:46:19","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/34828","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/comments?post=34828"}],"version-history":[{"count":1,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/34828\/revisions"}],"predecessor-version":[{"id":159767,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/posts\/34828\/revisions\/159767"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media\/26229"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/media?parent=34828"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/categories?post=34828"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/en\/wp-json\/wp\/v2\/tags?post=34828"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}