Следует ли мне избегать использования инструкций Java Label?
сегодня у меня был коллега, который предложил мне рефакторинг моего кода, чтобы использовать оператор label для управления потоком через 2 вложенных цикла for, которые я создал. Я никогда не использовал их раньше, потому что лично я думаю, что они снижают читаемость программы. Однако я готов изменить свое мнение об их использовании, если аргумент достаточно тверд. Каковы мнения людей о заявлениях лейбла?
11 ответов:
многие алгоритмы выражаются более легко, если вы можете перейти через два цикла (или цикл, содержащий оператор switch). Не расстраивайся из-за этого. С другой стороны, это может указывать на чрезмерно сложное решение. Так что отойдите и посмотрите на проблему.
некоторые люди предпочитают подход "один вход, один выход" для всех циклов. То есть, избегая разрыва (и продолжения) и раннего возврата для циклов в целом. Это может привести к некоторому дублированию кода.
Что бы я сделал настоятельно избегайте введения вспомогательных переменных. Скрытие потока управления в состоянии добавляет путаницы.
разбиение помеченных петель на два метода вполне может быть сложным. Исключения, вероятно, слишком тяжелы. Попробуйте один вход, один выход подход.
метки похожи на goto: используйте их экономно, и только тогда, когда они делают ваш код быстрее и что еще более важно, более понятно,
например, если вы находитесь в больших петлях глубиной шесть уровней, и вы сталкиваетесь с условием, которое делает остальную часть цикла бессмысленной для завершения, нет смысла иметь 6 дополнительных люков в ваших заявлениях о состоянии, чтобы выйти из цикла рано.
ярлыки (и Гото) не злые, это просто так иногда люди используют их в плохих целях. Большую часть времени мы на самом деле пытаемся написать наш код, чтобы он был понятен вам и следующему программисту, который приходит. Создание uber-fast является вторичной проблемой (будьте осторожны с преждевременной оптимизацией).
когда ярлыки (и goto) используются неправильно, они делают код менее читаемым, что вызывает горе для вас и следующего разработчика. Компилятору все равно.
есть несколько случаев, когда вам нужны ярлыки, и они могут быть запутанными, потому что они редко используются. Однако, если вам нужно использовать один, то используйте один.
кстати: это компилируется и работает.
class MyFirstJavaProg { public static void main(String args[]) { http://www.javacoffeebreak.com/java101/java101.html System.out.println("Hello World!"); } }
Мне любопытно услышать, какова ваша альтернатива ярлыкам. Я думаю, что это в значительной степени сводится к аргументу "return as early as possible" против "use a variable to hold the return value, and only return at the end."
метки довольно стандартны, когда у вас есть вложенные циклы. Единственный способ, которым они действительно уменьшают читаемость, - это когда другой разработчик никогда не видел их раньше и не понимает, что они означают.
Я никогда не видел ярлыки, используемые "в дикой природе" в Java-коде. Если вы действительно хотите разбить вложенные циклы, посмотрите, можете ли вы рефакторировать свой метод так, чтобы оператор раннего возврата делал то, что вы хотите.
технически, я думаю, что нет большой разницы между ранним возвращением и ярлыком. Практически, однако, почти каждый разработчик Java видел раннее возвращение и знает, что он делает. Я бы предположил, что многие разработчики, по крайней мере, будут удивлены ярлыком и, вероятно, будут смущенный.
меня учили единственному входу / единственному выходу православия в школе, но с тех пор я стал ценить ранние заявления о возврате и вырваться из циклов как способ упростить код и сделать его более ясным.
Я бы поспорил в пользу них в некоторых местах, я нашел их особенно полезными в этом примере:
nextItem: for(CartItem item : user.getCart()) { nextCondition : for(PurchaseCondition cond : item.getConditions()) { if(!cond.check()) continue nextItem; else continue nextCondition; } purchasedItems.add(item); }
Я думаю, что с новым циклом for-each метка может быть действительно ясной.
например:
sentence: for(Sentence sentence: paragraph) { for(String word: sentence) { // do something if(isDone()) { continue sentence; } } }
Я думаю, что это выглядит действительно ясно, если ваша метка такая же, как и ваша переменная в новом for-each. На самом деле, возможно, Java должна быть злой и добавлять неявные метки для-каждой переменной heh
я использовал цикл с надписью Java для реализации метода сита для поиска простых чисел (выполненный для одной из математических задач Эйлера проекта), что сделало его в 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 вложенных цикла и на определенных условиях, вы хотите вернуться к внешний цикл.
таким образом, у них есть свои применения, это зависит от проблемы, которую вы пытались решить.
Я никогда не использую метки в моем коде. Я предпочитаю создать guard и инициализировать его в null или другое необычное значение. Этот охранник часто является объектом результата. Я не видел ни одного из моих коллег, использующих ярлыки, и не нашел их в нашем репозитории. Это действительно зависит от вашего стиля кодирования. На мой взгляд, использование меток уменьшит читаемость, поскольку это не обычная конструкция, и обычно она не используется в Java.
Да, вы должны избегать использования label, если нет конкретной причины их использовать (пример этого, упрощающий реализацию алгоритма, уместен). В таком случае я бы посоветовал добавить достаточные комментарии или другую документацию, чтобы объяснить причины этого, чтобы кто-то не пришел позже и не искалечил его из какого-то понятия "улучшения кода" или "избавления от запаха кода" или какого-то другого потенциального оправдания BS.
Я бы приравнял такого рода вопрос с решением, когда следует или не следует использовать троичный if. Главное обоснование заключается в том, что это может затруднить читаемость, и если программист не будет очень осторожен, чтобы назвать вещи разумным образом, то использование соглашений, таких как ярлыки, может сделать вещи намного хуже. Предположим, например, используя 'nextCondition' и 'nextItem' использовали 'loop1 и loop2 для имени метки.
лично этикетки являются одной из тех особенностей, которые не имеют большого смысла для меня, за пределами Ассемблер или базовый и другие столь же ограниченные языки. Java имеет множество более обычных / регулярных петлевых и управляющих конструкций.
Я обнаружил, что метки иногда полезны в тестах, чтобы отделить обычную настройку, выполнять упражнения и проверять фазы и группировать связанные операторы. Например, используя терминологию 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(); }
ваши варианты форматирования могут отличаться, но основная идея заключается в том, что метки в этом случае обеспечивают заметное различие между логическими разделами, содержащими ваш тест, лучше, чем комментарии. Я думаю, что Спок библиотека просто строится на этой самой функции, чтобы объявить ее тест фазы.