Являются ли глобальные константы антипаттерном?
-
13-09-2019 - |
Вопрос
Я всегда считал, что создание класса только ради хранения констант — плохой дизайн.Но недавно я попробовал поискать в Google и нашел только то, что интерфейс поскольку константы - это плохой антишаблон - нет упоминания об использовании класса констант.
Я придерживаюсь мнения, что, поскольку класс констант на самом деле мало чем отличается от глобальных переменных, поэтому я против этого и склонен отрефакторить такие классы.Он создает класс данных, который не имеет абсолютно никакого контекста.Гораздо лучше привязать эти константы к тому, что на самом деле их использует, чтобы придать им контекст и значение, а также инкапсулировать их в класс.
Что думают другие люди?
Решение
Глобальные константы не являются плохой практикой, если они...
- ...неизменяемый - глобальный,
final
/readonly
ссылка на изменяемый объект (например, JavaArrayList<T>
или С#List<T>
) — это не постоянное, а глобальное состояние. - ...нужен >1 классу.Если константы нужны только одному классу, поместите константы непосредственно в класс.(Предостережение:Соответствующим образом сбалансируйте СУХОЙ и ЯГНИ.)
Блох рассматривает «постоянный интерфейс» и «интерфейс констант».проблема «постоянного класса» в «Эффективной Java» и защищает подход «постоянного класса».Причина, по которой вам не нужны константы в интерфейсе, заключается в том, что это побуждает клиентские классы «реализовать» этот интерфейс (чтобы получить доступ к константам без префикса имени интерфейса).Однако не следует этого делать: интерфейс на самом деле не является интерфейсом к возможностям объекта, а является удобством времени компиляции, заложенным во внешнем типе класса.Учти это:
interface C { public static final int OMGHAX = 0x539; }
class A implements C { ... }
class B { private A a; }
Сорт B
теперь излишне зависит от C
.Если реализация A
изменяется так, что ему не нужны константы из C
, ты не можешь удалить implements C
из него, не нарушая его внешний интерфейс - кто-то (возможно, очень глупый человек, но таких людей предостаточно) может сослаться на A
объект через C
ссылка!
Помещая константы в класс и делая этот класс неэкземплярным, вы сообщаете клиентам, что класс констант на самом деле функционирует просто как подпространство имен.В C# вы отмечаете класс как static
, на Java вы бы хотели это сделать final
и дайте недоступный конструктор:
final class C {
private C() { throw new AssertionError("C is uninstantiable"); }
public static final int OMGHAX = 0x539;
}
Если вы программируете на Java и хотите, чтобы константы не начинались с имени класса констант, вы можете использовать import static
функциональность.
И да, немного излишне заставлять создавать новый тип только для того, чтобы было куда поместить ваши константы, но это проблема таких языков, как Java и C#, с которой нам приходится иметь дело - мы иметь поставить наши константы где-то, и наш лучший вариант — класс, не создающий экземпляра.
Другие советы
Глобальные константы в порядке.
Глобальные (непостоянные) переменные — дело рук дьявола.
Глобальные переменные являются проблематичными, поскольку они вводят в значительной степени ненужные зависимости между модулями.Эти зависимости затрудняют отладку проблем и повторное использование кода.
Я бы сказал это действительно глобальные константы также проблематичны по той же причине. Поэтому вместо создания синглтона MyGlobals, содержащего константу типа MyGlobals.HTTP_SUCCESS_OK, упакуйте подобные константы вместе в их собственные классы, например HttpStatus.SUCCESS_OK.
Я считаю, что проблема глобальных переменных заключается в том, что они создают глобальное состояние.Глобальные константы этого не делают, но они действительно отвечают за некоторые бесконтекстные константы, что может быть плохо.
Если вам нужны подобные вещи, я бы посоветовал создать перечисления (если у вас есть константы int) или статические классы для констант, чтобы вы могли дать им некоторый контекст (например, Math.PI)
Я полагаю, что одна вещь, о которой не упоминается, — это более прагматичные вопросы.Если вы используете компилируемый язык, имейте в виду, что вам придется перекомпилировать, чтобы изменить значение константы.Если это значение, которое вы, возможно, захотите часто менять, вы также можете рассмотреть возможность использования файла конфигурации.
В некоторых случаях глобальные константы являются идеальным вариантом, если они действительно постоянны (не только постоянны для одной сборки программы, но, предположительно, на протяжении всего жизненного цикла программного продукта и далее).
Например, вы не захотите иметь несколько классов, каждый из которых объявляет свою константу для pi, e или HTTP_SUCCESS.
С другой стороны, глобальные константы могут создать множество проблем, связанных с глобальными переменными, если они представляют собой произвольные значения, которые можно изменить, например.из-за изменения требований.Т.е.если размещение этих констант в файле конфигурации кажется разумным вариантом, это не должна быть глобальная константа.
Глобальные переменные широко признаны как плохая вещь, и их, как правило, следует избегать.Вот почему у многих людей возникают проблемы с шаблоном Singleton.Проблема с глобальными переменными в том, что они транзитивны.