Я программирую на Java уже несколько лет, но недавно я вернулся в школу, чтобы получить официальную степень. Я был очень удивлен, узнав, что в моем последнем задании я потерял очки за использование цикла, подобного приведенному ниже.
do{
//get some input.
//if the input meets my conditions, break;
//Otherwise ask again.
} while(true)
Теперь для моего теста я просто сканирую какой-то консольный ввод, но мне сказали, что такой цикл не рекомендуется, потому что использование break
сродни тому goto
, что мы просто не делаем.
Я полностью понимаю подводные камни goto
и его двоюродный брат Java break:label
, и у меня есть здравый смысл не использовать их. Я также понимаю, что более полная программа предоставила бы некоторые другие средства спасения, скажем, например, просто для завершения программы, но это не было причиной, по которой говорил мой профессор, так что ...
Что не так с do-while(true)
?
источник
break
, вероятно, имеет смысл, но на самом деле неправильно понято. Возможно, вы можете обучить своего профессора этому;) По моему опыту, профессора мало знают о ремесле программирования.do {} while (true)
эквивалентно тому,while(true) {}
что последнее гораздо более общепринятая форма и намного яснее.break
, он должен попробовать программирование на языке без него. Это не займет слишком много циклов, прежде чем вы захотите этого!Ответы:
Я бы не сказал, что это плохо, но в равной степени я бы обычно искал альтернативу.
В ситуациях, когда это первое, что я пишу, я почти всегда, по крайней мере, пытаюсь преобразовать это в нечто более понятное. Иногда с этим ничего не поделаешь (или альтернатива - иметь
bool
переменную, которая не делает ничего значащего, кроме указания конца цикла, менее наглядно, чемbreak
утверждение), но ее стоит хотя бы попробовать.В качестве примера того, где его использовать проще,
break
чем флаг, рассмотрим:Теперь давайте заставим его использовать флаг:
Я считаю последнее более сложным для чтения: у него есть дополнительный
else
блок, темactOnInput
более отступ, и если вы пытаетесь понять, что происходит приtestCondition
возвратеtrue
, вам нужно внимательно просмотреть оставшуюся часть блока, чтобы убедиться, что это не то , что после того, как вelse
блоке , который будет происходить лиrunning
установлено значениеfalse
или нет.break
Заявление сообщается намерение более четко, и позволяет остальной блок ужиться с тем, что он должен делать , не заботясь о прежних условиях.Обратите внимание, что это точно такой же аргумент, как и у людей о множественных операторах возврата в методе. Например, если я могу обработать результат метода в первых нескольких строках (например, из-за того, что некоторые входные данные являются нулевыми, пустыми или нулевыми), я нахожу более ясным возвращать этот ответ напрямую, чем иметь переменную для хранения результата. , то целый блок другого кода, и , наконец
return
, заявление.источник
while (true)
AFAIK ничего, правда. У учителей просто аллергия
goto
, потому что они слышали где-то, что это действительно плохо. В противном случае вы просто напишите:Что почти одно и то же.
Может быть, это чище (потому что вся информация о цикле содержится в верхней части блока):
источник
У Дугласа Крокфорда было замечание о том, что ему бы хотелось, чтобы JavaScript содержал
loop
структуру:И я не думаю, что Java будет еще хуже иметь
loop
структуру.Там нет ничего плохого с
while(true)
петлями, но есть тенденция для учителей , чтобы препятствовать их. С точки зрения преподавания очень легко заставить учеников создавать бесконечные циклы и не понимать, почему цикл никогда не избегается.Но они редко упоминают, что все циклические механизмы могут быть воспроизведены с помощью
while(true)
циклов.такой же как
и
такой же как:
и
такой же как:
До тех пор , как вы можете настроить свои петли таким образом , что работает конструкцию , что вы выбираете для использования не имеет значения. Если это произойдет , чтобы поместиться в
for
петле, используйтеfor
цикл.Одна последняя часть: держите ваши петли простыми. Если на каждой итерации требуется много функциональности, поместите ее в функцию. Вы всегда можете оптимизировать его после того, как оно заработало.
источник
for
циклами, когдаcontinue
операторы задействованы, но они не являются основным расширением.for (;;) {
? (Произносится "навсегда"). Раньше это было очень популярно.Еще в 1967 году Эдгар Дейкстра написал статью в отраслевом журнале о том, почему goto следует исключать из языков высокого уровня для улучшения качества кода. Из этого вышла целая парадигма программирования, называемая «структурированное программирование», хотя, конечно, не все согласны с тем, что goto автоматически означает плохой код.
Суть структурированного программирования заключается в том, что структура кода должна определять его поток, а не иметь сбои, разрывы или продолжение определения потока, где это возможно. Аналогично, наличие нескольких точек входа и выхода в цикл или функцию также не рекомендуется в этой парадигме.
Очевидно, что это не единственная парадигма программирования, но часто она может быть легко применена к другим парадигмам, таким как объектно-ориентированное программирование (аля Java).
Возможно, ваших учителей учили, и они стараются научить ваш класс, что лучше избегать «кода спагетти», следя за тем, чтобы наш код был структурированным, и следовал подразумеваемым правилам структурированного программирования.
Хотя в реализации, в которой используется break, нет ничего изначально «неправильного», некоторые считают, что значительно проще читать код, в котором условие цикла явно указывается в условии while (), и исключает некоторые возможности быть слишком хитрыми. Существуют определенные недостатки в использовании условия while (true), которое, как представляется, часто появляется в коде начинающими программистами, например, риск случайного создания бесконечного цикла или создания кода, который трудно читать или излишне запутывает.
По иронии судьбы, обработка исключений - это та область, в которой отклонение от структурированного программирования, безусловно, проявится и ожидается, когда вы углубитесь в программирование на Java.
Также возможно, что ваш инструктор ожидал, что вы продемонстрируете свою способность использовать определенную структуру цикла или синтаксис, который преподается в этой главе или уроке вашего текста, и хотя написанный вами код функционально эквивалентен, вы, возможно, не демонстрировали особый навык, который вы должны были изучить на этом уроке.
источник
Обычное Java-соглашение для чтения ввода:
И обычное соглашение C ++ для чтения ввода:
И в C это
или если вы уверены, что знаете, какова самая длинная строка текста в вашем файле, вы можете сделать
Если вы проверяете, ввел ли ваш пользователь
quit
команду, легко расширить любую из этих трех структур цикла. Я сделаю это на Java для вас:Итак, хотя, безусловно, бывают случаи, когда
break
илиgoto
это оправдано, если все, что вы делаете, - это чтение файла или консоли построчно, то вам не нуженwhile (true)
цикл для этого - ваш язык программирования уже предоставил вам с подходящей идиомой для использования команды ввода в качестве условия цикла.источник
while (true)
цикл вместо одного из этих обычных входных циклов, вы можете забыть проверить конец файла.while
условное выражение . В конечном Java-состоянии оно уже становится довольно здоровенным, и, если вам нужно было проделать огромные манипуляции, чтобы решить, продолжать или нет, это может занять довольно много времени. Вы можете разделить его на отдельные функции, и это может быть лучше. Но если вы действительно хотите, чтобы это выполнялось в одной функции, и перед принятием решения о том, следует ли продолжить, нужно выполнить нетривиальную работуwhile(true)
.gets()
это не обычное соглашение. Это очень способствует переполнению буфера.fgets(buffer, BUFFER_SIZE, file)
это больше похоже на стандартную практику.fgets
.Это не такая страшная вещь, но вы должны учитывать других разработчиков при кодировании. Даже в школе.
Ваши коллеги-разработчики должны видеть предложение выхода для вашего цикла в объявлении цикла. Ты этого не делал. Вы спрятали предложение выхода в середине цикла, чтобы больше работать для того, кто придет и попытается понять ваш код. Это та же самая причина, по которой избегают таких вещей, как «разрыв».
Тем не менее, вы все равно увидите такие вещи в большом количестве кода в реальном мире.
источник
while (true)
довольно очевидно , что он будет внутриbreak
илиreturn
внутри, или что он будет работать вечно. Быть прямым очень важно, ноwhile(true)
не особенно плохо само по себе. Переменные, которые имеют сложные инварианты в итерациях цикла, могут быть примером чего-то, что вызывает гораздо большую тревогу.Это твой пистолет, твоя пуля и твоя нога ...
Это плохо, потому что ты напрашиваешься на неприятности. Не вы или кто-либо из других постеров на этой странице будут иметь примеры коротких / простых циклов while.
Проблемы начнутся в очень случайное время в будущем. Это может быть вызвано другим программистом. Это может быть человек, устанавливающий программное обеспечение. Это может быть конечный пользователь.
Зачем? Я должен был выяснить, почему приложение 700K LOC постепенно начинает сжигать 100% процессорного времени, пока каждый процессор не будет насыщен. Это был удивительный (истинный) цикл. Это было большим и противным, но это сводилось к:
Там не было финальной еще ветки. Если значение не соответствует условию if, цикл продолжает работать до конца времени.
Конечно, программист обвинил конечных пользователей в том, что они не выбрали значение, которое ожидал программист. (Затем я удалил все экземпляры while (true) в коде.)
ИМХО, это не очень хорошее защитное программирование - использовать конструкции вроде while (true). Он вернется, чтобы преследовать тебя.
(Но я помню, что профессора понизили рейтинг, если бы мы не комментировали каждую строку, даже для i ++;)
источник
Это плохо в том смысле, что конструкции структурированного программирования предпочтительнее (несколько неструктурированные) операторы break и continue. Для сравнения, они предпочитают «идти» по этому принципу.
Я всегда рекомендовал бы сделать ваш код максимально структурированным ... хотя, как отмечает Джон Скит, не делайте его более структурированным!
источник
Согласно моему опыту, в большинстве случаев петли имеют «основное» условие для продолжения. Это условие, которое должно быть записано в сам оператор while (). Все остальные условия, которые могут нарушить цикл, являются вторичными, не столь важными и т. Д. Они могут быть записаны как дополнительные
if() {break}
операторы.while(true)
часто сбивает с толку и менее читабелен.Я думаю, что эти правила не охватывают 100% случаев, но, вероятно, только 98% из них.
источник
Хотя это не обязательно ответ на вопрос, почему бы не использовать
while (true)
, я всегда нашел это комическое и сопровождающее авторское утверждение лаконичным объяснением того, почему нужно делать, а не делать.Что касается вашего вопроса: нет никаких проблем с
... если вы знаете, что делаете, и убедитесь, что
exit_time
в какой-то моментtrue
.Учителя отговаривают вас от использования,
while(true)
потому что до тех пор, пока вы точно не знаете, что делаете, это простой способ сделать критическую ошибку.источник
exit_time = false; while(!exit_time) { execute_stuff(); }
иdo { execute_stuff(); } while(! exit_time );
оба гораздо понятнее, чем наличиеif( condition ) { break; }
в конце цикла сwhile(true)
. Разрывы - это короткие замыкания в циклах - прекрасно, если они используются в качестве короткого замыкания в середине цикла, но вы должны просто оценить условие в операторе while и иметь разрыв в конце цикла.Вы можете просто использовать логический флаг, чтобы указать, когда заканчивать цикл while.
Break
иgo to
были причины для того, чтобы программное обеспечение было трудно поддерживать - кризис программного обеспечения (tm) - и его следует избегать, и легко может быть.Вопрос в том, прагматичны вы или нет. Прагматичные кодеры могут просто использовать break в этой простой ситуации.
Но это хорошо, чтобы избавиться от привычки не использовать их, иначе вы можете использовать их вне привычки в неподходящих ситуациях, например, в сложных вложенных циклах, где удобочитаемость и удобство сопровождения вашего кода становятся сложнее при использовании
break
.источник
if (running)
внутри цикла, с отступом всего остального кода, когда все, что я хочу - это выйти из цикла, для меня определенно менее понятно, чем простое выражение break, в котором точно указано , что я хочу сделать. Вы, кажется, рассматриваете использование разрыва как вредную привычку аксиоматически - я не думаю об этом как таковой.Может быть, мне не повезло. Или, может быть, мне просто не хватает опыта. Но каждый раз , когда я вспоминаю дело с
while(true)
имеяbreak
внутри, можно было улучшить код, применяя метод извлечения к блоку while , который сохранял,while(true)
но (по совпадению?) Преобразовывал всеbreak
s вreturn
s.По моему опыту
while(true)
без перерывов (то есть с возвратами или бросками) довольно удобно и легко понять.источник
Я думаю, что да, это довольно плохо ... или, по крайней мере, для многих разработчиков. Это симптоматично для разработчиков, которые не думают о своих условиях цикла. Следовательно, есть склонность к ошибкам.
источник
Там нет никаких серьезных проблем с
while(true)
сbreak
заявлениями, однако некоторые могут подумать , его немного снижает читаемость кода. Попробуйте дать переменным значимые имена, оцените выражения в нужном месте.Для вашего примера гораздо понятнее сделать что-то вроде:
Это особенно верно, если цикл do while становится длинным - вы точно знаете, где находится проверка, чтобы увидеть, происходит ли дополнительная итерация. Все переменные / функции имеют соответствующие имена на уровне абстракции. Это
while(true)
утверждение говорит вам, что обработка не в том месте, о котором вы думали.Может быть, вы хотите другой вывод во второй раз через цикл. Что-то вроде
кажется мне более читабельным
Опять же, с тривиальным примером оба вполне читабельны; но если цикл стал очень большим или глубоко вложенным (что означает, что вы, вероятно, уже должны были выполнить рефакторинг), первый стиль может быть немного более понятным.
источник
Я использую нечто подобное, но с противоположной логикой, во многих моих функциях.
источник
Это скорее эстетика, гораздо проще читать код, когда вы явно знаете, почему цикл остановится прямо в объявлении цикла.
источник
Я бы сказал, что, как правило, причина, по которой это не считается хорошей идеей, заключается в том, что вы не используете конструкцию в полной мере. Кроме того, я склонен думать, что многим инструкторам не нравится, когда их ученики приходят с «багажом». Я имею в виду, что им нравится оказывать основное влияние на стиль программирования своих студентов. Так что, возможно, это просто любимая мозоль инструктора.
источник
Для меня проблема заключается в удобочитаемости.
Оператор while с истинным условием ничего не говорит о цикле. Это усложняет задачу понимания этого.
Что будет легче понять из этих двух фрагментов?
источник
Я думаю, что использование перерыва для вашего учителя - это как сломать ветку дерева, чтобы получить плод, использовать другие приемы (склонить ветку), чтобы получить плод, а ветвь все еще жива :)
источник
1) Нет ничего плохого в
do -while(true)
2) Ваш учитель не прав.
NSFs !!:
3) Большинство учителей являются учителями, а не программистами.
источник
Это может быть плохо, если ваш цикл выполняется в фоновом потоке, поэтому, когда вы закрываете свое приложение, прерывая поток пользовательского интерфейса, этот фрагмент кода будет продолжать выполняться. Как уже говорили другие, вы всегда должны использовать какую-то проверку, чтобы обеспечить способ отмены.
источник