Я не считаю полезным в наши дни спорить о том, что делает, а что не представляет собой единственную ответственность или единственную причину перемен. Я бы предложил на его месте принцип минимальной скорби:
Принцип минимального горя: код должен либо стремиться свести к минимуму вероятность необходимости изменений, либо максимально облегчить изменение.
Как это? Не следует стремиться к тому, чтобы выяснить, почему это может помочь снизить затраты на техническое обслуживание, и, надеюсь, это не должно быть предметом бесконечных дискуссий, но, как и в случае с SOLID, в общем, это не то, что можно применять вслепую повсюду. Это то, что нужно учитывать при балансе компромиссов.
Что касается вероятности требующих изменений, это уменьшается с:
- Хорошее тестирование (улучшенная надежность).
- Вовлечение только минимального кода, необходимого для выполнения чего-то конкретного (это может включать в себя уменьшение афферентных связей).
- Просто сделайте код плохим в том, что он делает (см. Принцип Make Badass).
Что касается сложности внесения изменений, то это связано с эфферентными связями. Тестирование вводит эфферентные муфты, но повышает надежность. Сделанный хорошо, он, как правило, приносит больше пользы, чем вреда, и является полностью приемлемым и продвигается по принципу минимального горя.
Принцип «задира»: классы, которые используются во многих местах, должны быть классными. Они должны быть надежными, эффективными, если это связано с их качеством и т. Д.
А Принцип «Сделай Злобу» связан с Принципом Минимальной Скорби, так как злые вещи найдут меньшую вероятность требующих изменений, чем вещи, которые сосут из того, что они делают.
Я бы начал с указания на упомянутый выше парадокс, а затем указал бы, что SRP сильно зависит от уровня детализации, который вы хотите учитывать, и что если вы зайдете достаточно далеко, любой класс, содержащий более одного свойства или один метод, нарушает Это.
С точки зрения SRP у класса, который почти ничего не делает, наверняка есть только одна (иногда нулевая) причина для изменения:
class Float
{
public:
explicit Float(float val);
float get() const;
void set(float new_val);
};
Это практически не имеет причин для изменения! Это лучше, чем SRP. Это ЗРП!
За исключением того, что я хотел бы предположить, что это является вопиющим нарушением принципа «Сделай Злобу» Это также абсолютно бесполезно. То, что делает так мало, не может надеяться быть задирой. В нем слишком мало информации (TLI). И, естественно, когда у вас есть что-то, что является TLI, оно не может сделать что-то действительно значимое, даже с информацией, которую оно инкапсулирует, поэтому оно должно просочиться в внешний мир в надежде, что кто-то на самом деле сделает что-то значимое и злобное. И эта утечка в порядке для чего-то, что просто предназначено для агрегирования данных и ничего более, но этот порог является разницей, как я вижу, между «данными» и «объектами».
Конечно, то, что является TMI, также плохо. Мы могли бы поместить все наше программное обеспечение в один класс. Это может даже иметь только один run
метод. И кто-то может даже возразить, что теперь у него есть одна очень широкая причина для изменения: «Этот класс нужно менять только в том случае, если программное обеспечение нуждается в улучшении». Я глупый, но, конечно, мы можем представить все проблемы с обслуживанием.
Таким образом, существует баланс между гранулярностью или грубостью объектов, которые вы проектируете. Я часто судю об этом по тому, сколько информации вы должны просочиться во внешний мир, и сколько функциональных возможностей он может выполнять. Я часто нахожу там принцип Make Badass, чтобы найти баланс, сочетая его с принципом минимальной скорби.