У меня есть класс для расчета чистого годового дохода работников. У него есть константа, представляющая процент налога. Но однажды ставка налога изменилась, поэтому мне нужно исправить код.
Указывает ли акт исправления этой константы на нарушение принципа Открыто-Закрыто , поскольку он постулирует, что класс должен быть закрыт для модификации?
object-oriented
object-oriented-design
solid
Анализ Paradisys
источник
источник
Ответы:
OCP может быть лучше понят, если подумать о классах или компонентах, предоставляемых поставщиком A в какой-то библиотеке черного ящика, для использования пользователями B, C и D (обратите внимание, что это просто ментальная модель, которую я использую для ясности, не имеет значения, если в действительности единственным пользователем класса является сам А.).
Если B, C и D могут использовать или повторно использовать предоставленные классы для разных вариантов использования, без необходимости изменения исходного кода библиотеки, тогда компонент удовлетворяет требованиям OCP ( в отношении категории вариантов использования ). Есть разные способы для достижения этой цели, как
сделать класс наследуемым (обычно в сочетании с шаблоном метода шаблона или шаблоном стратегии)
предоставляя «точки внедрения» для внедрения зависимости
путем предоставления параметров конфигурации для класса или компонента (например, с помощью параметра конструктора «процент налога», как в вашем случае, или с помощью какого-либо другого механизма конфигурации)
может быть, другие средства, в зависимости от языка программирования или экосистемы
Типичные примеры, которые вы найдете в учебниках, часто бывают первого или второго типа (я полагаю, потому что, по мнению авторов этих книг, третий тип слишком тривиален, чтобы о нем упоминать).
Как видите, это не имеет ничего общего с запретом любых изменений исходного кода поставщиком A (например, для исправления ошибок, оптимизации или добавления новых функций обратно совместимым образом), что совершенно не связано с OCP. OCP рассказывает о том, как A проектирует интерфейс и детализацию компонентов в lib, поэтому различные сценарии повторного использования (например, повторное использование с различными налоговыми ставками) не вызывают автоматически требования к изменениям.
Поэтому, несмотря на то, что вам здесь говорят другие, ответ однозначно «да» , это будет нарушением OCP.
РЕДАКТИРОВАТЬ: кажется, между кем-то написал подробный пост в блоге именно на эту тему. Хотя некоторые его части можно было бы сформулировать лучше (как указал Дерек Элкинс), автор, как правило, разделяет мою точку зрения о том, что «выполнение OCP» - это не абсолютная собственность, а нечто, что можно оценить только в контексте определенного категории изменений требований.
источник
Как говорят другие, в идеале класс дохода работника позволил бы параметризовать константу, делая этот класс независимым от этой величины.
В конечном счете, вызывающее приложение может также разрешить параметризацию с точки зрения внешней конфигурации (например, файла). Получив внешнюю конфигурацию, мы можем изменить ставку налога - хотя учтите, что если файл конфигурации читается только один раз при запуске, то приложение должно быть перезапущено, чтобы обновленные проценты налога вступили в силу, так что это нужно сохранить разум. Мы могли бы предоставить функцию приложения для перечитывания конфигурации, когда это было сделано, или мы могли бы предоставить более сложный механизм, который замечает, когда файл конфигурации изменяется ...
В долгосрочной перспективе вы можете обнаружить, что налоговые вопросы требуют больше, чем просто процент - например, что в один прекрасный день налоговое законодательство является более сложным и требует нескольких процентов и некоторых констант (например, сумма менее 10 тыс. Долл., Облагаемая налогом в X%, в то время как остаток облагается налогом по Y%).
По сути, это предполагает использование шаблона стратегии, в котором рассматриваемый основной класс принимает объект стратегии для расчета налога.
Различные стратегии (а также константы% и $) должны выбираться из файла конфигурации, и теперь добавление новой стратегии требует добавления нового кода, но не обязательно обновления существующего кода.
Каждая стратегия может знать, как анализировать / интерпретировать свои внешние аргументы конфигурации, а также как рассчитывать фактический налог.
Динамически, налог может также зависеть от языка управления, поэтому язык может быть связан с заработком или с сотрудниками (или с обоими). Во внешней конфигурации мы можем связать локаль с налоговой стратегией.
Также посмотрите внедрение зависимости , где мы управляем этими вещами явно.
источник
Если вам нужно изменить класс для изменения налоговой стоимости, его дизайн действительно нарушает OCP. Для того, что вы описали до сих пор, подходящим вариантом является то, чтобы класс калькулятора принял значение налога в качестве параметра.
Если ваш класс является экземпляром (то есть это не статический класс), создав свойство класса налоговой переменной, значение которого вводится через конструктор, вы также улучшите связность классов.
Короче говоря, ваш текущий дизайн делает ваш класс зависимым от константного значения, которое на самом деле не является константой (определяя константу как значение, которое никогда не изменится, несмотря ни на что, например, на значение PI). Это нарушает OCP. Измените дизайн, чтобы получить значение налога в качестве аргумента конструктора.
источник
Полностью согласен с @Becuzz, и я просто хочу подвести итог: OCP - это поиск повторно используемых (и, следовательно, полезных) абстракций, которые вводятся в класс. Таким образом, поведение класса изменяется не путем изменения его кода, а путем предоставления ему различных реализаций. Это предельно ясно из книги Роберта Мартина « Гибкая разработка программного обеспечения, принципы, шаблоны и практики », см. Соответствующую главу «Принцип открытого и закрытого типа», подраздел «Абстракция - ключ». Это разъясняет еще одно заблуждение, что поведение может быть изменено только с помощью наследования. Именно Бертран Мейер предложил в 1988 году в своей книге « Построение объектно-ориентированного программного обеспечения », а не Роберт Мартин.
источник
На мой взгляд, это не является нарушением принципа открытого закрытого типа. Тем не менее, тот факт, что что-то, что обязательно должно изменяться во времени (например, процент налога), является константой, является недостатком дизайна: вам следует изменить не значение константы, а то, как вы обрабатываете процент налога. Это должен быть тип настройки, который можно изменить без перекомпиляции всего.
источник