Рубрики
Без рубрики

Константы на Java: шаблоны и анти-шаблоны

Узнайте об использовании констант на Java с акцентом на общие шаблоны и анти-шаблоны

Автор оригинала: Amy DeGregorio.

1. Введение

В этой статье мы узнаем об использовании констант на Java с акцентом на общие шаблоны и анти-шаблоны.

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

2. Основы

Константа – это переменная, значение которой не изменится после того, как она будет определена.

Давайте посмотрим на основы для определения константы:

private static final int OUR_CONSTANT = 1;

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

3. Анти-паттерны

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

3.1. Волшебные числа

Магические числа являются числовой буквалом в блоке кода:

if (number == 3.14159265359) {
    // ...
}

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

3.2. Большой глобальный класс констант

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

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

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

С другой стороны, Компилятор Java помещает значение константы в ссылки на переменные в классах, в которых мы используем их . Таким образом, если мы изменим одну из наших констант в нашем классе констант и только перекомпоним этот класс, а не класс ссылок, мы можем получить несовместимые постоянные значения.

3.3. Постоянный интерфейс анти-шаблон

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

Определим постоянный интерфейс для калькулятора:

public interface CalculatorConstants {
    double PI = 3.14159265359;
    double UPPER_LIMIT = 0x1.fffffffffffffP+1023;
    enum Operation {ADD, SUBTRACT, MULTIPLY, DIVIDE};
}

Далее мы реализуем нашу КалькуляторКонстанты интерфейс:

public class GeometryCalculator implements CalculatorConstants {    
    public double operateOnTwoNumbers(double numberOne, double numberTwo, Operation operation) {
       // Code to do an operation
    }
}

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

Во-вторых, использование постоянного интерфейса открывает нам проблемы времени времени, вызванные затенением поля. Давайте посмотрим, как это может произойти, определив UPPER_LIMIT постоянная в пределах нашей ГеометрияКалкулятор класс:

public static final double UPPER_LIMIT = 100000000000000000000.0;

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

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

4. Шаблоны

Ранее мы рассматривали соответствующую форму для определения констант. Давайте рассмотрим некоторые другие хорошие практики для определения констант в наших приложениях.

4.1. Общие добрые практики

Если константы логически связаны с классом, мы можем просто определить их там. Если мы рассматриваем набор констант как членов перечисленного типа, мы можем использовать enum определить их.

Давайте определим некоторые константы в Калькулятор класс:

public class Calculator {
    public static final double PI = 3.14159265359;
    private static final double UPPER_LIMIT = 0x1.fffffffffffffP+1023;
    public enum Operation {
        ADD,
        SUBTRACT,
        DIVIDE,
        MULTIPLY
    }

    public double operateOnTwoNumbers(double numberOne, double numberTwo, Operation operation) {
        if (numberOne > UPPER_LIMIT) {
            throw new IllegalArgumentException("'numberOne' is too large");
        }
        if (numberTwo > UPPER_LIMIT) {
            throw new IllegalArgumentException("'numberTwo' is too large");
        }
        double answer = 0;
        
        switch(operation) {
            case ADD:
                answer = numberOne + numberTwo;
                break;
            case SUBTRACT:
                answer = numberOne - numberTwo;
                break;
            case DIVIDE:
                answer = numberOne / numberTwo;
                break;
            case MULTIPLY:
                answer = numberOne * numberTwo;
                break;
        }
        
        return answer;
    }
}

В нашем примере мы определили константу для UPPER_LIMIT что мы только планируем использовать в Калькулятор класса, так что мы установили его на частные . Мы хотим, чтобы другие классы могли использовать ИП и Операция enum, так что мы поставили их на общественные .

Рассмотрим некоторые преимущества использования enum для Операция . Первое преимущество заключается в том, что он ограничивает возможные значения. Представьте себе, что наш метод берет строку для значения операции с ожиданием, что одна из четырех постоянных строк поставляется. Мы можем легко предвидеть сценарий, при котором разработчик, вызывая метод, отправляет свое собственное значение строки. С enum , значения ограничены теми, которые мы определяем. Мы также видим, что энумы особенно хорошо подходят для использования в переключить Заявления.

4.2. Класс Константы

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

Давайте создадим МатемКонстантс класс:

public final class MathConstants {
    public static final double PI = 3.14159265359;
    static final double GOLDEN_RATIO = 1.6180;
    static final double GRAVITATIONAL_ACCELERATION = 9.8;
    static final double EULERS_NUMBER = 2.7182818284590452353602874713527;
    
    public enum Operation {
        ADD,
        SUBTRACT,
        DIVIDE,
        MULTIPLY
    }
    
    private MathConstants() {
        
    }
}

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

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

5. Заключение

В этой статье мы рассмотрели плюсы и минусы некоторых из наиболее популярных шаблонов и анти-шаблонов, замеченных при использовании констант в Java. Мы начали с некоторых основных правил форматирования, прежде чем о них анти-шаблоны. Узнав о нескольких общих анти-шаблонов, мы посмотрели на модели, которые мы часто видим, применяется к константы.

Как всегда, код доступен более на GitHub .