Являются ли глобальные константы антипаттерном?

StackOverflow https://stackoverflow.com/questions/1263954

Вопрос

Я всегда считал, что создание класса только ради хранения констант — плохой дизайн.Но недавно я попробовал поискать в Google и нашел только то, что интерфейс поскольку константы - это плохой антишаблон - нет упоминания об использовании класса констант.

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

Что думают другие люди?

Это было полезно?

Решение

Глобальные константы не являются плохой практикой, если они...

  1. ...неизменяемый - глобальный, final/readonly ссылка на изменяемый объект (например, Java ArrayList<T> или С# List<T>) — это не постоянное, а глобальное состояние.
  2. ...нужен >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.Проблема с глобальными переменными в том, что они транзитивны.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top