В SOLID, в чем разница между SRP и ISP? (Принцип единой ответственности и принцип разделения интерфейсов)

Чем SOLID "Принцип разделения интерфейса" отличается от "Принципа единой ответственности"?

Запись в Википедии для SOLID говорит, что

Интернет-провайдер разбивает очень большие интерфейсы на более мелкие и более специфичные, чтобы клиенты могли знать только о методах, которые им интересны

Однако для меня это звучит как применение SRP к интерфейсам и классам. В конце концов, если интерфейс отвечает только за одну концептуальную вещь, вы не сможете разбить его дальше.

Я что-то упустил, или ISP вроде избыточно с SRP? Если нет, то что ISP подразумевает, что SRP нет?

6 ответов

Решение

SRP сообщает нам, что в модуле должна быть только одна ответственность.

Интернет-провайдер говорит нам, что вы не должны сталкиваться с чем-то большим, чем вам нужно на самом деле. Если вы хотите использовать print() метод из интерфейса IВы не должны создавать экземпляр SwimmingPool или DriveThru класс для этого.

Конкретнее, и если перейти прямо к делу, то это разные взгляды на одну и ту же идею - SRP больше ориентирован на точку зрения на стороне дизайнера, а ISP больше ориентирован на точку зрения на стороне клиента., Так что ты в принципе прав.

Все пришло

Интернет-провайдер был впервые использован и сформулирован Робертом К. Мартином при консультировании Xerox. Компания Xerox создала новую систему принтеров, которая могла выполнять различные задачи, такие как сшивание набора печатных документов и отправка факсов. Программное обеспечение для этой системы было создано с нуля и успешно выполняло свои задачи. По мере роста программного обеспечения внесение изменений становилось все более и более трудным, поэтому даже малейшее изменение могло бы занять цикл перераспределения до часа. Это делало практически невозможным продолжение развития. Проблема дизайна заключалась в том, что один основной класс Job использовался почти всеми задачами. Каждый раз, когда нужно было выполнить задание на печать или сшивание, был вызван какой-либо метод в классе Job. Это привело к огромному или "толстому" классу с множеством методов, специфичных для различных клиентов. Из-за этого дизайна основная работа знала бы обо всех методах печати, хотя они были бесполезны.

так

Решение, предложенное Мартином, сегодня называется принципом разделения интерфейсов. Применительно к программному обеспечению Xerox был добавлен слой интерфейсов между классом Job и всеми его клиентами с использованием принципа инверсии зависимостей. Вместо того, чтобы иметь один большой класс Job, был создан интерфейс Staple Job или Print Job, который будет использоваться классами Staple или Print, соответственно, вызывая методы класса Job. Поэтому для каждого задания был создан один интерфейс, который был реализован классом Job.

@ http://en.wikipedia.org/wiki/Interface_segregation_principle

SRP занимается тем, что делает модуль, и как это делается, запрещая любое сочетание уровней абстракции. По сути, если компонент может быть детально определен одним предложением, он не будет нарушать SRP.

С другой стороны, провайдер заботится о том, как использовать модуль, имеет ли смысл использовать только часть модуля, игнорируя при этом некоторые аспекты.

В качестве примера кода, который поддерживает дух или SRP, но может сломать ISP, является шаблон Фасада. Он несет единственную ответственность, "предоставляя упрощенный доступ к более крупной подсистеме", но если базовой подсистеме необходимо демонстрировать совершенно разные взгляды, это нарушает работу интернет-провайдера.

Тем не менее, обычно, когда фрагмент кода нарушает принцип SOLID, он часто нарушает весь код. Конкретные примеры, которые нарушают определенный принцип при сохранении остальных, в природе редки.

Роберт Мартин написал в Твиттере следующее 16 мая 2018 года.

ISP можно рассматривать как похожий на SRP для интерфейсов; но это больше, чем это. ISP обобщается следующим образом: "Не зависите от большего, чем вам нужно". SRP обобщает так: "Собирайте вещи, которые меняются по одним и тем же причинам и в одно и то же время".

Представьте себе класс стека с push и pop. Представьте себе клиента, который только подталкивает. Если этот клиент зависит от интерфейса стека, он зависит от pop, который ему не нужен. SRP не будет отделять толчок от поп-музыки; ISP будет.

SRP и ISP в конечном итоге сводятся к одному и тому же. Для реализации любого из них требуется разделение классов или интерфейсов.

Однако есть различия на других фронтах.

  1. Нарушение SRP может иметь далеко идущие последствия для всей конструкции, вызывая плохую ремонтопригодность, повторное использование и, конечно, низкую когезию и сцепление.
  2. SRP влияет как на поведенческие, так и на структурные компоненты структуры объекта.
  3. Повторное проектирование на основе нарушения SRP требует более глубокого анализа, требует целостного рассмотрения различных компонентов дизайна.

Нарушение ISP в основном связано с плохой читабельностью (и в некоторой степени низкой сплоченностью). Но влияние на обслуживание и повторное использование кода гораздо менее зловещее, чем SRP.

Кроме того, рефакторинг кода в соответствии с ISP, кажется, просто структурное изменение.

Смотрите также мой блог для SRP и ISP

С точки зрения моего понимания, оба принципа дополняют друг друга, т.е. их нужно сочетать.

Конечным последствием нарушения ISP становится хрупкость, «хирургия дробовика» или «эффект бабочки». Много кода может сломаться или потребовать обновления кода, потому что они зависят от некоторого интерфейса или объектов, которые предоставляют больше, чем им нужно. Изменения становятся чрезмерными.

Последствием нарушения SRP в основном является снижение удобочитаемости и обслуживания. Отсутствие четкой структуры кода может потребовать от людей поиска по кодовой базе (одна ответственность слишком распределена) или в пределах одного большого блока (множество обязанностей, сваленных вместе), чтобы внести последовательное изменение. В общем, это увеличивает накладные расходы, чтобы полностью понять задачу (цель) некоторого фрагмента кода. Изменения предотвращены.

Таким образом, оба принципа действуют как нижняя и верхняя граница разумного управления изменениями.

Примеры для удовлетворения RSP без интернет-провайдера, предоставленные другими ответами, показывают, что может быть код, который действительно будет принадлежать друг другу (например, цитата из примера стека от Роберта К. Мартина). Но он может делать слишком много, перепроектирован и т. д. Может быть, в очень маленьких примерах эффект не виден, но если он становится большим, может быть удобнее, чтобы зависимый класс по-прежнему правильно компилировался после некоторой несвязанной части в ( косвенная) зависимость была изменена. Вместо того, чтобы больше не компилировать, потому что были изменены несвязанные вещи.

Ключевые отличия:

Объем:

SRP: Он фокусируется на обязанностях класса, гарантируя, что у класса есть только одна причина для изменений.

Интернет-провайдер: Основное внимание уделяется проектированию интерфейсов, гарантируя, что они не перегружены ненужными методами, а клиенты не зависят от методов, которые им не нужны. Уровень абстракции:

SRP: Он применяется на уровне класса и определяет обязанности внутри одного класса.

ISP: Он применяется на уровне интерфейса, касаясь того, как интерфейсы разрабатываются и используются классами. Обеспокоенность:

SRP: Речь идет о сплоченности классов и ремонтопригодности.

Интернет-провайдер: Он направлен на минимизацию зависимостей и повышение гибкости.

Другие вопросы по тегам