Как определить, соответствует ли класс принципу единой ответственности?

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

Но как мы определяем, обладает ли конкретный класс набором обязанностей и, таким образом, просто очень сплочен или имеет только одну ответственность и, таким образом, придерживается SRP? Другими словами, не является ли это более или менее субъективным, так как некоторые могут считать класс очень зернистым (и, как таковые, будут считать, что класс придерживается SRP), в то время как другие могут считать его недостаточно гранулированным?

31 голос | спросил user1483278 28 J0000006Europe/Moscow 2012, 22:20:45

8 ответов


16

Почему да, это субъективная тема very , и это тема многих программистов-программистов с горячим, красным лицом.

На самом деле нет ни одного ответа, и ответ может измениться по мере того, как ваше программное обеспечение становится более сложным. То, что когда-то было одной четко определенной задачей, может в конечном итоге стать множеством нечетко определенных задач. Это тоже трясет. Как вы выбираете правильный способ разделить программу на задачи?

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

ответил Jason Baker 28 J0000006Europe/Moscow 2012, 23:16:47
12

Боб Мартин (дядя Боб), который создал SOLID принципы, из которых SRP является первым, говорит об этом (я перефразирую, не могу вспомнить фактические слова):

  

У класса должна быть только одна причина для изменения

Если у него есть несколько причин, он не придерживается SRP.

ответил Oded 28 J0000006Europe/Moscow 2012, 22:25:20
7

Я могу дать вам несколько эмпирических правил.

  • Насколько легко назвать класс? Если класс трудно назвать, это, вероятно, слишком много.
  • Сколько общедоступных методов имеет класс? 7 +/- 2 - хорошее эмпирическое правило. Если класс имеет более того, вы должны подумать о его разбиении на несколько классов.
  • Существуют ли сплошные группы общедоступных методов, используемых в отдельных контекстах?
  • Сколько частных методов или данных есть? Если класс имеет сложную внутреннюю структуру, вы, вероятно, должны реорганизовать его так, чтобы внутренние компоненты были упакованы в отдельные меньшие классы.
  • И самое легкое эмпирическое правило: насколько велик класс? Если у вас есть заголовочный файл C ++, содержащий один класс длиной более нескольких сотен строк, вам, вероятно, следует разделить его.
ответил Dima 29 J0000006Europe/Moscow 2012, 01:11:39
6

Принципы единой ответственности говорят, что каждый программный модуль должен иметь только одну причину изменения. В недавней статье дядя Боб объяснил «причину изменения»,

  

Однако, как вы думаете об этом принципе, помните, что причиной перемен являются люди. Это люди, которые требуют изменений. И вы не хотите путать этих людей или себя, смешивая код, который многие разные люди заботятся по разным причинам.

Далее он объяснил концепцию примером ЗДЕСЬ .

ответил theD 11 Mayam15 2015, 08:57:31
2

OO говорит, что классы представляют собой группировку данных, функциональность. Это определение оставляет много места для субъективной интерпретации.

Мы знаем, что классы должны быть четко и легко определены. Но, чтобы определить такой класс, мы должны иметь четкое представление о том, как класс вписывается в общий дизайн. Без требований типа водопада, которые, как ни парадоксально, считаются анти-паттернами ... этого трудно достичь.

Мы можем реализовать проект класса с архитектурой, которая работает в большинстве случаев, например MVC. В приложениях MVC мы предполагаем наличие данных, пользовательский интерфейс и требование об обмене двумя.

С базовой архитектурой легче определить случаи, когда нарушаются правила единой ответственности. НАПРИМЕР. Передача экземпляра пользовательского элемента управления в модальный.

ответил P.Brian.Mackey 28 J0000006Europe/Moscow 2012, 23:46:25
2

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

Целью принципа является «разделение» базы кода, поэтому код, относящийся к одной «ответственности», изолирован в одном блоке. Это облегчает поиск и понимание кода, и что более важно, это означает, что изменения в «ответственности» будут влиять только на единицу кода.

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

Итак, что это за «ответственность»? Это то, что может мыслить независимо от других изменений. Скажем, у вас есть программа, которая может сохранить некоторые настройки в файле конфигурации XML и может прочитать их обратно из файла. Является ли это одной ответственностью или «загружает» и «спасает» две разные обязанности? Любые изменения в формате или структуре файла потребуют изменения логики загрузки и сохранения. Поэтому это единая ответственность, которую должен представлять один класс. Теперь рассмотрим приложение, которое может экспортировать некоторые данные в формате CVS, Excel и XML. В этом случае легко представить, что один формат может меняться без влияния на другой. Если вы решите изменить разделитель в формате CVS, он не должен влиять на вывод Excel. Таким образом, в этом случае он должен быть представлен тремя отдельными классами (предположительно, используя один и тот же интерфейс).

ответил JacquesB 27 72016vEurope/Moscow11bEurope/MoscowSun, 27 Nov 2016 15:00:53 +0300 2016, 15:00:53
1

Просто для обсуждения, я выведу класс из JUCE под названием AudioSampleBuffer . Теперь этот класс существует для хранения фрагмента (или, возможно, довольно длинного фрагмента) аудио. Он знает количество каналов, количество выборок (на канал), по-видимому, привязано к 32-битовому плаву IEEE, а не к переменному числовому представлению или словазу (но это не проблема со мной). Существуют функции-члены, которые позволяют вам получать numChannels или numSamples и указатели на какой-либо конкретный канал. Вы можете сделать AudioSampleBuffer длиннее или короче. Я предполагаю, что первые нулевые подушки являются буфером, а последний усекает.

Есть несколько частных членов этого класса, которые используются для выделения пространства в специальной куче, которую использует JUCE.

Но это то, чего отсутствует AudioSampleBuffer (и у меня было несколько обсуждений с Jules об этом): член, называемый SampleRate. Как он может отсутствовать?

Единственная ответственность, которую должен выполнить AudioSampleBuffer, - это адекватно представить физический звук, который слышит, что его образцы представляют. Когда вы вводите AudioSampleBuffer из того, что читает звуковой файл или из потока, есть дополнительный параметр, который вы должны получить и передать вместе с AudioSampleBuffer в методы обработки (скажем, это фильтр), который должен знать частоту дискретизации или, в конечном итоге, к методу, который воспроизводит буфер, чтобы быть услышанным (или передает его в другое место). Безотносительно.

Но вам нужно продолжить этот SampleRate, который присущ конкретному звуку, живущему в AudioSampleBuffer, везде. Я видел код, где функция константа 44100.0f была передана функции, потому что программист, похоже, не знал, что еще делать.

Это пример того, что он не выполнил свою единственную ответственность.

ответил robert bristow-johnson 30 J0000006Europe/Moscow 2015, 00:05:53
1

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

Другим способом является чистая основа ООП-модели после реальных объектов. Его гораздо легче увидеть ответственность реальных объектов. Однако, если реальный объект слишком сложный, разбивайте его на несколько контагирующих объектов, каждый из которых несет свою ответственность.

ответил m3th0dman 30 J0000006Europe/Moscow 2015, 13:01:00

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132