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

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


person Aaron    schedule 05.09.2008    source источник
comment
Мне нравится, насколько ты непредубежден :) Я готов изменить свое мнение об их использовании   -  person luigi7up    schedule 06.02.2013
comment
(Поскольку вы можете помещать циклы в методы, это полностью эквивалентно одиночному/множественному/раннему выходу из методов.)   -  person greybeard    schedule 14.08.2016


Ответы (11)


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

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

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

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

person Tom Hawtin - tackline    schedule 05.09.2008
comment
Проголосовал бы за это, если бы не заключительная попытка, замечание о подходе к единственному входу и единственному выходу. - person Lawrence Dol; 22.05.2009
comment
Я думаю, что время от времени стоит примерять размер. У вас всегда есть ^Z. - person Tom Hawtin - tackline; 23.05.2009
comment
Скрытие потока управления внутри состояния добавляет путаницы. В целом это хороший совет. - person j_v_wow_d; 29.03.2016

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

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

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

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

person BIBD    schedule 05.09.2008
comment
Да, +1: GOTO не убивают приложения - программисты убивают приложения. - person Lawrence Dol; 22.05.2009
comment
Исторически сложилось так, что программисты использовали GOTO для уничтожения приложений. GOTO не просто так получил плохую репутацию. - person Michael Easter; 06.01.2010
comment
Все сводится к письму Дейкстры A Case Against the Goto Statement / Go To Statement считается вредным, которое выступает против него из-за тенденции превращать программу в спагетти-код, а не в нечто более структурированное. На самом деле вы все время используете goto (будь то перерыв, продолжение, попытка/поймать и т. д.). Почти всегда он отбрасывает исполнение вперед. Если вы не умеете двигаться только вперед, вы можете увеличить сложность функции на порядок. - person BIBD; 21.08.2017
comment
Переход назад может быть достаточно простым для вас, чтобы понять сегодня, но следующий разработчик или вы через 3 года захотите убить сукиного сына, который сэкономил 5 минут работы и оставил им 3 часа на разбор потока функции. - person BIBD; 21.08.2017

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

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

class MyFirstJavaProg {  
        public static void main(String args[]) {
           http://www.javacoffeebreak.com/java101/java101.html
           System.out.println("Hello World!");
        }
}
person Peter Lawrey    schedule 26.01.2009
comment
Да, и хорошая подсветка синтаксиса должна прояснить почему. - person Lawrence Dol; 22.05.2009
comment
Это ужасный вопрос на собеседовании, если только он не для компании, чья кодовая база совершенно запутана. Вы никогда не увидите это в дикой природе, а если и увидите, быстрый поиск в Интернете покажет вам, что это значит. Есть более важные вещи, на которых вы можете тестировать потенциальных разработчиков, а не маленькие глупые загадки. - person Reinstate Monica 2331977; 21.10.2013
comment
Подсветка и форматирование кода @studro покажет вам, о чем идет речь ;) Дело в том, что вы всегда найдете в чужом коде что-то не то, что вы бы сделали, или то, что вы ожидаете, и как вы с этим справляетесь. Важно то, как вы отвечаете на вопрос, а не ответ, который вы даете. Интервью должно быть связано с викториной о том, что вы знаете, но с чем бы вы хотели работать и как вы справляетесь с различными способами ведения дел. - person Peter Lawrey; 21.10.2013
comment
Это определенно неясно; здорово сказать, что это то, как вы с этим справляетесь, но это забава для бедного разработчика, который, к счастью, знает об этом, и исключающий фактор для хорошего разработчика, который не сталкивался с этим в дикой природе (потому что это не так). случаются так часто вообще). Я бы погуглил «этикетки на Java», вероятно, не подходит для интервью. - person Reinstate Monica 2331977; 21.10.2013

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

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

person Outlaw Programmer    schedule 05.09.2008
comment
Рекурсивный подход. Или вы можете условно сломать, если (найден) сломать; и иметь это в конце всех ваших петель. Вы также можете разделить внутренние циклы на методы и вернуть вместо разрыва. Вы также должны задаться вопросом о преимуществах раннего прерывания, можете ли вы повысить производительность за счет распараллеливания или другого алгоритма. В нескольких случаях я даже понял, что вложенность не нужна, циклы можно просто реорганизовать, чтобы они выполнялись один за другим. - person Didier A.; 17.08.2015

Я использовал цикл с меткой Java для реализации метода Sieve для поиска простых чисел (сделано для одной из математических задач проекта Эйлера), что сделало его в 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

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

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

person Selenia    schedule 20.04.2010

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

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

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

person Don Kirkby    schedule 05.09.2008

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


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

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

  }
  purchasedItems.add(item);
}
person Ceilingfish    schedule 26.01.2009
comment
Что ж, continue nextCondition — это лишнее просто шум. - person Lawrence Dol; 22.05.2009

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

Например:

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

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

person Pyrolistical    schedule 24.09.2008
comment
Что ж, continue sentence; не продолжает обрабатывать предложение, слова которого (которое?) были обработаны внутренним циклом: он продолжает обработку _следующего предложения_/того же абзаца. - person greybeard; 15.01.2016

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

person Bartosz Bierkowski    schedule 05.09.2008

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

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

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

person Jeremy Harton    schedule 10.04.2016

Я обнаружил, что метки иногда бывают полезны в тестах, чтобы разделить обычную настройку, упражнение и этапы проверки, а также сгруппировать связанные операторы. Например, используя терминологию 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 просто использует эту функцию для объявления фаз тестирования.

person polaretto    schedule 11.11.2016