Как мне уменьшить мой код с помощью функции при использовании большого количества ссылок, таких как PIXELS_PER_INCH = 72?

#java

#java

Вопрос:

У меня есть некоторый код, который нуждается в сокращении, и это было рекомендовано мне на Reddit.com для этого я использую функции. Но проблема в том, что код в основном представляет собой набор public static final «ссылок», таких как PIXELS_PER_INCH = 72 .

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

Вот пример того, как я присваиваю значения своим константам:

 public static final int PICTURES_4 = 0;
public static final int PICTURES_6 = 1;
public static final int PICTURES_8 = 2;
public static final int PICTURES_10 = 3;
public static final int PICTURES_12 = 4;

public static final int PICTURES_OPTION_0 = 4;
public static final int PICTURES_OPTION_1 = 6;
public static final int PICTURES_OPTION_2 = 8;
public static final int PICTURES_OPTION_3 = 10;
  

И вот пример того, где я использую эти постоянные ссылки:

 switch (settings.getInt(SettingsActivity.PICTURES_OPTION, SettingsActivity.DEFAULT_PICTURES_OPTION)) {
        case SettingsActivity.PICTURES_4:
            totalImages = SettingsActivity.PICTURES_OPTION_0;
            break;
        case SettingsActivity.PICTURES_6:
            totalImages = SettingsActivity.PICTURES_OPTION_1;
            break;
        case SettingsActivity.PICTURES_8:
            totalImages = SettingsActivity.PICTURES_OPTION_2;
            break;
  

По сути, я хотел бы знать, как использовать функцию для сокращения кода, но при этом сохранить возможность использовать читаемые ссылки. Или моя идея использовать читаемую ссылку неверна? На онлайн-уроке программирования я узнал об использовании констант в качестве читаемых ссылок (таких как PIXELS_PER_INCH = 72) вместо использования абсолютных значений.

Спасибо, что уделили мне время.

Обновление: В итоге я воспользовался предложениями aioobe и Ллойда Озимандиаса Форса. Я использовал EnumMap в цикле for. Однако в цикле for я по какой-то причине не смог использовать myEnumMap.values() . Я погуглил это и нашел другой способ сделать это с помощью myEnumMap.class.getEnumConstants() , вместо этого.

Комментарии:

1. Хотя константа PIXELS_PER_INCH в порядке, остальные из этих констант, похоже, заменяют одно магическое число на другое.

2. @Paul Butcher: Спасибо за ваш ответ. Я создал код таким образом, потому что считал удобочитаемость одним из наиболее важных аспектов программирования. Я хотел, чтобы читатели моего кода поняли, что я делал в своем операторе switch. Но выполнение этого таким образом сделало код слишком длинным, и читатели жалуются на это. Есть ли у вас какие-либо рекомендации по сохранению удобочитаемости при сокращении кода?

3. Не беспокойтесь о сокращении кода, подумайте о повышении удобочитаемости. Я не понимаю, почему этот переключатель / регистр преобразует (например) PICTURE_18 (7) в PICTURE_OPTION_7 (18). Что означают все эти цифры и какой цели вы пытаетесь достичь, переводя между ними? Попытайтесь выразить это намерение в коде.

4. Читаемость / понятность, безусловно, важны. И хотя макет хорош, все, что я (например) могу сказать, это то, что PICTURES_6 подразумевает PICTURES_OPTION_1 . Это бессмысленно. Дайте константам лучшие имена, такие как PICTURE_OPTION_RESIZE и SAVE_BUTTON_ICON , и читаемость значительно улучшится.

5. @Paul Butcher, @Andrzej Doyle, @aioobe, @Lloyd Ozymandias Сила: В моем приложении используется виджет для Android, называемый spinner. По сути, это выпадающее меню. Я вызываю метод get из счетчика, который возвращает число из списка на основе 0, представляющее опцию, выбранную в меню. Выбранный параметр — это просто число, и его нелегко прочитать. Итак, я создал константы, которые пытаются объяснить значение выбранной опции. Если пользователь выбирает вариант 1, это PICTURE_OPTION_0, а значение — PICTURE_4, потому что вариант 1 — это 4 картинки.

Ответ №1:

  • Вы можете поместить параметры в map и сделать get(option) вместо switch(option)

    Инициализируйте карту следующим образом:

     Map<Integer, Integer> optionsMap = new HashMap<Integer, Integer>() {{
        put(SettingsActivity.PICTURES_4, SettingsActivity.PICTURES_OPTION_0);
        put(SettingsActivity.PICTURES_6, SettingsActivity.PICTURES_OPTION_1);
        ...
    }};
      

    а затем замените переключатель следующим образом:

     totalImages = optionsMap.get(settings.getInt(SettingsActivity.PICTURES_OPTION,
                                       SettingsActivity.DEFAULT_PICTURES_OPTION));
      
  • Или (поскольку у вас, похоже, простое преобразование целого числа в целое) вы могли бы поместить свои значения в таблицу поиска.

  • Или вы можете поместить это в функцию и заменить все разрывы возвратами:

     public int getPictureOption() {
        switch (settings.getInt(SettingsActivity.PICTURES_OPTION,
                                SettingsActivity.DEFAULT_PICTURES_OPTION)) {
                case SettingsActivity.PICTURES_4:
                    return SettingsActivity.PICTURES_OPTION_0;
    
                case SettingsActivity.PICTURES_6:
                    return SettingsActivity.PICTURES_OPTION_1;
    
                case SettingsActivity.PICTURES_8:
                    return SettingsActivity.PICTURES_OPTION_2;
        }
    }
      

    а затем выполните

     totalImages = getPictureOption();
      

Если вы считаете, что ваши константы говорят сами за себя, вы могли бы избавиться от всех SettingsActivity. , добавив статический импорт в начало вашего файла:

 import static your.package.SettingsActivity.*;
  

Комментарии:

1. Спасибо за ваш ответ. Люди, которым я показывал свой код, сказали, что мои инструкции switch слишком длинные. В реальном коде мои операторы switch имеют длину около 16 операторов case, поскольку код PICTURES_# и PICTURES_OPTION_ # продолжается. Мне было интересно, смогу ли я сохранить читаемость своего кода при использовании функции для сокращения кода. Удобочитаемость с точки зрения «что делает этот оператор switch?» С длинной версией кода несколько легче понять, что происходит, но она слишком длинная.

2. Обновлен первый вариант в моем ответе.

3. Я думаю, что помещу свои константы в EnumMap и воспользуюсь вашим первым предложением. Спасибо за вашу помощь.

Ответ №2:

Не включайте значения enum — это задание для полиморфизма или таблицы Map / look up, как упоминалось aiobe.

Чтобы проиллюстрировать один из методов работы с перечислениями в Java, рассмотрим следующий параметр SettingsActivity enum с полиморфным методом getPictureOption() . Он объявлен абстрактным в теле перечисления, заставляя каждую константу перечисления реализовывать этот метод. Этот метод более подробно описан в Effective Java 2nd Edition (Джош Блох).

 enum SettingsActivity {
    OPTION_1(){
        public int getPicureOption() {
            return  myValue * 6;
        }
    },
    OPTION_2(){
        public int getPictureOption() {
            return Math.pow(myValue,5);
        }
    },
    ...
    OPTION_N() {
        public int getPictureOption() {
            return myValue-6;
        }
    };

    private final int myValue;

    private SettingsActivity(int myValue) {
        this.myValue = myValue;
    }

    // enums can have abstract methods!
    public abstract int getPictureOption();
}

SettingsActivity foo = getSettingsActivityFromSomewhere();

// polymorphic getPictureOption method - we don't
// know which activity was clicked
int something = foo.getPictureOption();
  

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

В случае, если вы хотите использовать Map, класс EnumMap, предоставляемый JDK, предоставляет сверхэффективную реализацию Map для перечислений (он реализован в виде одного длинного значения для перечислений с менее чем 65 константами и массива длинных значений для > 64 констант). В любом случае, операции поиска равны O (1) (в отличие от O (lg n) для хэш-карты).

Комментарии:

1. Спасибо за ваш ответ. На самом деле, SettingsActivity не является перечислением. Это класс, а константы являются статическими константами (такими как PICTURES_#). Это был единственный известный мне способ получить доступ к переменной из одного класса, находясь в другом классе.

2. Спасибо за ваше предложение использовать EnumMap. Я воспользуюсь этим и первым предложением aioobe.