Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

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

Впервые появилось в выпуске журнала Code Magazine за январь/февраль 2010 года и доступно в Интернете по адресу "SOLID Software Development, один шаг за раз"


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

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

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

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

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

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

Ответ 2

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

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

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

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

Ответ 3

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

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

Разница тонкая, но мне помогает. Рассмотрим пример wikipedia об устройстве создания отчетов:

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

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

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

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

Ответ 4

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

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

Ответ 5

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

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

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

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

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

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

Ответ 6

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

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

Мне не очень понятно, что такое ответственность, а доказательство - количество вопросов, которые возникают в этой концепции.

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

или

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

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

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

Например:

class Modem
  send()
  receive()

Refactors to ==>

class ModemSender
class ModelReceiver

+

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

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