Согласно документации Microsoft, статье SOLID Wikipedia SOLID или большинству ИТ-архитекторов мы должны гарантировать, что каждый класс несет только одну ответственность. Я хотел бы знать почему, потому что, если все, кажется, согласны с этим правилом, никто не соглашается с причинами этого правила.
Некоторые ссылаются на лучшее обслуживание, другие говорят, что оно облегчает тестирование или делает класс более надежным или безопасным. Что правильно и что это на самом деле означает? Почему это облегчает обслуживание, облегчает тестирование или делает код более надежным?
design-patterns
architecture
solid
single-responsibility
Бастьен Вандамме
источник
источник
Ответы:
Модульность. Любой приличный язык даст вам возможность склеить куски кода, но нет общего способа отсоединить большой кусочек кода, если программист не выполнит операцию на источнике. Заклинив множество задач в одной конструкции кода, вы лишаете себя и других возможности комбинировать их части другими способами и вводите ненужные зависимости, которые могут привести к тому, что изменения в одной части окажут влияние на другие.
SRP так же применим к функциям, как и к классам, но основные языки ООП относительно плохо склеивают функции.
источник
Лучшее обслуживание, простое тестирование, быстрое исправление ошибок - это только (очень приятные) результаты применения SRP. Основная причина (по выражению Роберта С. Матина):
Другими словами, СРП вызывает смену населенного пункта .
SRP также продвигает СУХОЙ код. Пока у нас есть классы, которые несут только одну ответственность, мы можем использовать их где угодно. Если у нас есть класс с двумя обязанностями, но нам нужен только один из них, а второй вмешивается, у нас есть 2 варианта:
источник
Легко создать код для решения конкретной проблемы. Сложнее создать код, который устраняет эту проблему и позволяет безопасно вносить изменения в будущем. SOLID предоставляет набор методов, которые делают код лучше.
Что касается того, который является правильным: все три из них. Все они являются преимуществами использования единой ответственности и причины, по которой вы должны ее использовать.
Что касается того, что они имеют в виду:
Попробуйте создать код на некоторое время, следуя этому принципу, а затем повторите этот код, чтобы внести некоторые изменения. Вы увидите огромное преимущество, которое оно дает.
Вы делаете то же самое с каждым классом, и в итоге получаете больше классов, все в соответствии с SRP. Это делает структуру более сложной с точки зрения связей, но простота каждого класса оправдывает это.
источник
Вот аргументы, которые, на мой взгляд, подтверждают утверждение о том, что принцип единой ответственности является хорошей практикой. Я также предоставляю ссылки на дополнительную литературу, где вы можете прочитать даже более подробные рассуждения - и более красноречивые, чем мои:
Лучшее обслуживание : в идеале, всякий раз, когда функциональность системы должна меняться, должен быть один и только один класс, который должен быть изменен. Четкое соответствие между классами и обязанностями означает, что любой разработчик, участвующий в проекте, может определить, к какому классу это относится. (Как отметил @ MaciejChałapuk, см. Роберт С. Мартин, «Чистый код» .)
Более простое тестирование : в идеале классы должны иметь как можно меньший открытый интерфейс, а тесты должны затрагивать только этот открытый интерфейс. Если вы не можете проверить с ясностью, потому что многие части вашего класса являются частными, то это явный признак того, что у вашего класса слишком много обязанностей, и что вы должны разделить его на более мелкие подклассы. Обратите внимание, что это относится также к языкам, где нет «публичных» или «частных» учеников; наличие небольшого общедоступного интерфейса означает, что клиентскому коду очень ясно, какие части класса предполагается использовать. (См. Кент Бек, «Разработка через тестирование» для более подробной информации.)
Надежный код : ваш код не будет отказывать более или менее часто, потому что он хорошо написан; но, как и весь код, его конечная цель не в том, чтобы общаться с машиной , а с коллегами-разработчиками (см. Кент Бек, «Шаблоны реализации» , Глава 1.) Четкая база кода легче рассуждать, поэтому будет меньше ошибок. и между обнаружением ошибки и ее устранением будет меньше времени.
источник
Есть ряд причин, но мне нравится подход, использованный многими ранними программами UNIX: хорошо делать одну вещь. Это достаточно сложно сделать с одной вещью, и чем больше вы пытаетесь сделать, тем труднее.
Другой причиной является ограничение и контроль побочных эффектов. Мне понравилась моя комбинация открывания двери кофеварки. К сожалению, кофе обычно переполнялся, когда у меня были посетители. Я забыл закрыть дверь после того, как я сделал кофе на днях, и кто-то украл его.
С психологической точки зрения вы можете отслеживать только несколько вещей одновременно. Общие оценки - семь плюс или минус два. Если класс делает несколько вещей, вам нужно отслеживать их все одновременно. Это снижает вашу способность отслеживать, что вы делаете. Если класс делает три вещи, и вы хотите только одну из них, вы можете исчерпать свою способность отслеживать вещи, прежде чем вы действительно что-то сделаете с классом.
Выполнение нескольких вещей увеличивает сложность кода. Помимо самого простого кода, увеличение сложности увеличивает вероятность ошибок. С этой точки зрения вы хотите, чтобы классы были максимально простыми.
Тестирование класса, который делает одну вещь, намного проще. Вам не нужно проверять, что второе действие класса выполнялось или не происходило для каждого теста. Вам также не нужно исправлять нарушенные условия и проводить повторную проверку, если один из этих тестов не пройден.
источник
Потому что программное обеспечение органично. Требования постоянно меняются, поэтому вам нужно как можно меньше манипулировать компонентами. Не следуя принципам SOLID, вы можете получить кодовую базу, заданную в бетоне.
Представьте себе дом с несущей бетонной стеной. Что происходит, когда вы снимаете эту стену без какой-либо поддержки? Дом, вероятно, рухнет. В программном обеспечении мы этого не хотим, поэтому мы структурируем приложения таким образом, чтобы вы могли легко перемещать / заменять / изменять компоненты, не причиняя большого ущерба.
источник
Я следую за мыслью
1 Class = 1 Job
.Использование физиологической аналогии: мотор (нейронная система), дыхание (легкие), пищеварительный (желудок), обонятельный (наблюдение) и т. Д. Каждый из них будет иметь подмножество контроллеров, но каждый из них будет иметь только 1 ответственность, независимо от того, нужно ли им управлять как работает каждая из их соответствующих подсистем или являются ли они подсистемой конечной точки и выполняют только одну задачу, такую как поднятие пальца или наращивание волосяного фолликула.
Не путайте тот факт, что он может действовать как менеджер, а не как работник. Некоторые работники в конечном итоге получают повышение до менеджера, когда выполняемая ими работа становится слишком сложной, чтобы один процесс не мог справиться сам по себе.
Самая сложная часть того, что я испытал, это знание того, когда назначать класс в качестве оператора, супервизора или менеджера процесса. В любом случае вам необходимо соблюдать и обозначать его функциональность для 1 ответственности (Оператор, Супервайзер или Менеджер).
Когда класс / объект выполняет более одной из этих ролей типа, вы обнаружите, что у всего процесса начнутся проблемы с производительностью или узкие места процесса.
источник
Lung
класс, я бы сказал, что экземплярPerson
должен все еще существоватьBreathe
, и, таким образом,Person
класс должен содержать достаточно логики, чтобы как минимум делегировать обязанности, связанные с этим методом. Кроме того, я бы предположил, что лес взаимосвязанных объектов, которые доступны только через общего владельца, часто легче рассуждать, чем лес, имеющий несколько независимых точек доступа.Person
класс имеет в своей работе делегирование всей функциональности, связанной с чудовищно сложным объектом «реальный мир-человек», включая объединение его различных частей. , Заставить сущность делать 500 вещей - это уродливо, но если так работает моделируемая реальная система, иметь класс, который делегирует 500 функций, сохраняя при этом одну идентичность, может быть лучше, чем делать все с непересекающимися частями.Person
но при этом сообщать о цепочке в случае успеха / неудачи, но не обязательно влиять на другой. 500 функций (хотя и приведенных в качестве примера, было бы за бортом и не поддерживается), я стараюсь, чтобы этот тип функциональности был производным и модульным.Fred.vision.lookAt(George)
имеет смысл, но разрешение сказать, что кодsomeEyes = Fred.vision; someTubes = Fred.digestion
кажется странным, так как затеняет отношения междуsomeEyes
иsomeTubes
.Особенно с таким важным принципом, как «Единая ответственность», я лично ожидал бы, что есть много причин, по которым люди принимают этот принцип.
Некоторые из этих причин могут быть:
Также обратите внимание, что SRP поставляется с набором принципов SOLID. Соблюдать SRP и игнорировать все остальное так же плохо, как и не выполнять SRP. Таким образом, вы не должны оценивать SRP отдельно, но в контексте всех принципов SOLID.
источник
... test is not affected by other responsibilities the class has
Не могли бы вы уточнить это?Лучший способ понять важность этих принципов - это иметь потребность.
Когда я был начинающим программистом, я не задумывался о дизайне, на самом деле, я даже не знал, что существуют шаблоны проектирования. Поскольку мои программы росли, изменение одной вещи означало изменение многих других вещей. Было трудно отследить ошибки, код был огромным и повторяющимся. Не было особой иерархии объектов, вещи были повсюду. Добавление чего-то нового или удаление чего-то старого вызовет ошибки в других частях программы. Пойди разберись.
В небольших проектах это может не иметь значения, но в больших проектах все может быть очень кошмарно. Позже, когда я натолкнулся на концепции дизайнерских шаблонов, я сказал себе: «О, да, это сделало бы все намного проще».
Вы действительно не можете понять важность шаблонов проектирования, пока не возникнет необходимость. Я уважаю шаблоны, потому что по своему опыту могу сказать, что они делают обслуживание кода простым и надежным.
Однако, как и вы, я все еще не уверен в «простом тестировании», потому что у меня еще не было необходимости проходить юнит-тестирование.
источник
Ответ заключается в том, что, как отмечали другие, все они верны, и все они связаны друг с другом, легче тестировать, облегчают обслуживание, делают код более надежным, облегчают обслуживание и так далее ...
Все это сводится к ключевому принципалу - код должен быть настолько маленьким и делать как можно меньше для выполнения работы. Это относится как к приложению, файлу или классу, так и к функции. Чем больше вещей выполняет фрагмент кода, тем сложнее его понять, поддерживать, расширять или тестировать.
Я думаю, что это можно выразить одним словом: сфера. Обратите пристальное внимание на область действия артефактов: чем меньше будет область действия в любой конкретной точке приложения, тем лучше.
Расширенная сфера = больше сложности = больше возможностей для того, чтобы что-то пошло не так.
источник
Если класс слишком большой, становится трудно поддерживать, тестировать и понимать, другие ответы покрывали эту волю.
У класса может быть больше одной ответственности без проблем, но вы скоро столкнетесь с проблемами со слишком сложными классами.
Однако наличие простого правила «только одна ответственность» просто помогает узнать, когда вам нужен новый класс .
Однако определить «ответственность» сложно, это не значит «делать все, что говорит спецификация приложения», реальный навык в том, чтобы разбить проблему на маленькие части «ответственности».
источник