Как определить, насколько грубой или мелкозернистой должна быть "ответственность" при использовании принципа единой ответственности?


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

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

Мне любопытно, если есть ли кто-нибудь, у кого есть какие-либо стратегии для "scoping", принцип единой ответственности, который немного менее объективен?

6 22

6 ответов:

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

Следующее впервые появилось в выпуске журнала Code за январь/февраль 2010 года и доступно в интернете по адресу "S. O. L. I. D. Software Development, One Step at a Time"


Принцип Единой Ответственности говорит, что класс должен иметь один, и только одна причина, чтобы измениться.

Это может показаться нелогичным в первый. Не проще ли было бы сказать: что класс должен иметь только один причина для существования? Вообще-то, никто. причина для существования может быть очень легко доведен до крайности, что вызовет больше вреда, чем пользы. Если ты возьмешь его к себе ... вот экстремальные и строят классы, которые есть одна причина, чтобы существовать, вы можете закончить только один метод на класс. Это вызвало бы большое разрастание занятия даже для самых простых из них процессы, заставляющие систему быть трудно понять и трудно изменить.

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

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

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

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

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

Чтобы лучше понять это, вероятно, полезно четко разграничить то, за что отвечает класс, и то, что делает метод. Метод должен "делать только одну вещь" (например, добавить два числа, хотя для большинства целей " + " - это метод, который делает это уже), в то время как класс должен представлять единую четкую "ответственность" перед своими потребителями. Это ответственность на гораздо более высоком уровне, чем метод.

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

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

Я склонен мыслить в терминах "скорости изменения" бизнес-требований, а не" причины для изменения".

Вопрос в том, насколько вероятно, что вещества изменятсявместе , а не могут ли они измениться или нет.

Разница тонкая, но она мне помогает. Давайте рассмотрим пример на Википедии О механизме отчетности:
  • Если вероятность того, что содержание и шаблон отчета изменятся одновременно, высока, то может быть одним компонентом, потому что они, по-видимому, связаны. (Это также может быть два)

  • Но если вероятность того, что содержание изменится без шаблона, важна, то она должна состоять из двух компонентов, потому что они не связаны. (Было бы опасно иметь его)

Но я знаю, что это личная интерпретация SRP.

Кроме того, второй прием, который мне нравится: "опишите свой класс в одном предложении". Обычно это помогает мне идентифицировать себя. если есть четкая ответственность или нет.

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

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

@Derick bailey: хорошее объяснение
Некоторые дополнения:
вполне допустимо, что применение SRP является контекстуальной основой.
Остается открытым вопрос: существуют ли объективные способы определить, нарушает ли данный класс SRP ?

Некоторые контексты проектирования вполне очевидны ( например, пример автомобиля Дерика), но в остальном контексты, в которых поведение класса должно быть определено, остаются нечеткими много раз.

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

Как только разделение сделано, причины сохранить разделенные обязанности или снова объединить их в единую ответственность становятся очевидными сразу.

Я применил этот подход, и это привело к хорошим результатам для меня.

Но мой поиск искать " объективные способы определение классовой ответственности " все еще продолжается.

Я уважительно не согласен, когда Крис Никола выше говорит, что "класс должен представлять единственную четкую "ответственность" перед своими потребителями

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

"единственная причина для изменения"

Или

" если описание содержит слово "и" тогда его нужно разделить "

Приводит к вопросу: Где предел? В конце концов, любой класс с 2 открытыми методами имеет 2 причины для изменения, не так ли?

Для меня истинный SRP приводит к шаблону фасада, где у вас есть класс, который просто делегирует вызовы другим классам

Например:

class Modem
  send()
  receive()

Refactors to ==>

class ModemSender
class ModelReceiver

+

class Modem
  send() -> ModemSender.send()
  receive()  -> ModemReceiver.receive()

Мнения приветствуются