Следует ли избегать использования выражений Java Label?

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

Ответ 1

Многие алгоритмы выражаются легче, если вы можете перепрыгнуть через два цикла (или цикл, содержащий оператор switch). Не расстраивайся. С другой стороны, это может указывать на чрезмерно сложное решение. Поэтому откиньтесь назад и посмотрите на проблему.

Некоторые люди предпочитают подход с одиночной записью и единственным выходом для всех циклов. То есть избегать перерыва (и продолжить) и раннего возврата для циклов вообще. Это может привести к дублированию кода.

То, что я бы очень избегал, - это введение вспомогательных переменных. Скрытие потока управления внутри состояния добавляет к путанице.

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

Ответ 2

Ярлыки похожи на goto's: используйте их экономно, и только когда они делают ваш код быстрее и более важным, более понятным,

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

Ярлыки (и goto's) не являются злыми, это просто, что иногда люди используют их плохо. Большую часть времени мы на самом деле пытаемся написать наш код, поэтому он понятен для вас и следующего программиста, который приходит. Сделать его более uber-fast является вторичной проблемой (опасайтесь преждевременной оптимизации).

Когда ярлыки (и goto's) используются неправильно, они делают код менее читаемым, что вызывает горе для вас и следующего разработчика. Компилятору все равно.

Ответ 3

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

BTW: он компилируется и запускается.

class MyFirstJavaProg {  
        public static void main(String args[]) {
           http://www.javacoffeebreak.com/java101/java101.html
           System.out.println("Hello World!");
        }
}

Ответ 4

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

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

Ответ 5

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

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

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

Ответ 6

Я думаю, что с новым циклом for-each метка может быть действительно понятной.

Например:

sentence: for(Sentence sentence: paragraph) {
  for(String word: sentence) {
    // do something
    if(isDone()) {
      continue sentence;
    }
  }
}

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

Ответ 7

Я бы поспорил в пользу их в некоторых местах, я нашел их особенно полезными в этом примере:


nextItem: for(CartItem item : user.getCart()) {

  nextCondition : for(PurchaseCondition cond : item.getConditions()) {
     if(!cond.check())
        continue nextItem;
     else
        continue nextCondition;

  }
  purchasedItems.add(item);
}

Ответ 8

Я использую цикл с меткой Java для реализации метода Sieve для нахождения простых чисел (выполненных для одной из математических задач Euler проекта), что сделало его в 10 раз быстрее по сравнению с вложенными циклами. Например, если (определенное условие) вернется к внешнему циклу.

private static void testByFactoring() {
    primes: for (int ctr = 0; ctr < m_toFactor.length; ctr++) {
        int toTest = m_toFactor[ctr];
        for (int ctr2 = 0; ctr2 < m_divisors.length; ctr2++) {
            // max (int) Math.sqrt(m_numberToTest) + 1 iterations
            if (toTest != m_divisors[ctr2]
                        && toTest % m_divisors[ctr2] == 0) {
                continue primes; 
            }
        } // end of the divisor loop
    } // end of primes loop
} // method

Я попросил программиста на С++, насколько плохи маркированные петли, он сказал, что будет использовать их экономно, но иногда они могут пригодиться. Например, если у вас есть 3 вложенных цикла и для определенных условий вы хотите вернуться к самому внешнему циклу.

Таким образом, у них есть свое применение, это зависит от проблемы, которую вы пытаетесь решить.

Ответ 9

Я никогда не использую метки в своем коде. Я предпочитаю создавать охранник и инициализировать его нулевым или другим необычным значением. Этот охранник часто является объектом результата. Я не видел никого из моих коллег, использующих этикетки, и не нашел их в нашем репозитории. Это действительно зависит от вашего стиля кодирования. По-моему, использование меток уменьшало бы удобочитаемость, поскольку это не общая конструкция и обычно она не используется в Java.

Ответ 10

Да, вам следует избегать использования ярлыка, если нет конкретной причины их использования (пример его упрощения реализации алгоритма уместен). В таком случае я бы посоветовал добавить достаточные комментарии или другую документацию, чтобы объяснить причины этого, чтобы кто-то не пришел позже и не смог изгнать его из понятия "улучшить код" или "избавиться от запаха кода" или некоторые другие потенциальные оправдания BS.

Я бы приравнивал этот вопрос к решению, когда нужно или не следует использовать тройной if. Главное обоснование заключается в том, что оно может препятствовать читабельности, и если программист не очень осторожно называет вещи разумным образом, то использование конвенций, таких как ярлыки, может сделать вещи намного хуже. Предположим, что пример, использующий 'nextCondition' и 'nextItem', использовал 'loop1' и 'loop2' для своих имен ярлыков.

Личные ярлыки - одна из тех функций, которые не имеют большого смысла для меня, вне Assembly или BASIC и других языков с аналогичным ограничением. Java имеет множество более обычных/регулярных циклов и управляющих конструкций.

Ответ 11

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

@Test
public void should_Clear_Cached_Element() throws Exception {
    given: {
        elementStream = defaultStream();
        elementStream.readElement();
        Assume.assumeNotNull(elementStream.lastRead());
    }
    when:
        elementStream.clearLast();
    then:
        assertThat(elementStream.lastRead()).isEmpty();
}

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