посылка
Следующий код следует считать плохим тоном, независимо от языка или желаемой функциональности:
while( true ) {
}
Подтверждающие аргументы
while( true )
Петля плохая форма потому , что он:
- Разрывает подразумеваемый контракт цикла while.
- Объявление цикла while должно явно указывать единственное условие выхода.
- Подразумевается, что он зацикливается навсегда.
- Код внутри цикла должен быть прочитан, чтобы понять завершающее предложение.
- Циклы, которые повторяются бесконечно, не позволяют пользователю завершить программу изнутри программы.
- Неэффективно.
- Есть несколько условий завершения цикла, включая проверку на «истину».
- Склонен к ошибкам.
- Трудно определить, где разместить код, который всегда будет выполняться для каждой итерации.
- Приводит к излишне сложному коду.
- Автоматический анализ исходного кода.
- Для поиска ошибок, анализа сложности программы, проверок безопасности или автоматического получения любого другого поведения исходного кода без выполнения кода указание начальных условий нарушения позволяет алгоритмам определять полезные инварианты, тем самым улучшая показатели автоматического анализа исходного кода.
- Бесконечные петли.
- Если все всегда используют
while(true)
циклы for, которые не являются бесконечными, мы теряем способность кратко общаться, когда циклы фактически не имеют условия завершения. (Возможно, это уже произошло, поэтому вопрос спорный.)
Альтернатива "Перейти к"
Следующий код лучше:
while( isValidState() ) {
execute();
}
bool isValidState() {
return msg->state != DONE;
}
Преимущества
Нет флага. Нет goto
. Без исключения. Легко поменять. Легко читать. Легко исправить. Дополнительно код:
- Изолирует информацию о рабочей нагрузке цикла от самого цикла.
- Позволяет кому-то поддерживать код для простого расширения функциональности.
- Позволяет назначать несколько условий завершения в одном месте.
- Отделяет завершающее предложение от кода для выполнения.
- Безопаснее для АЭС. ;-)
Второй момент важен. Не зная, как работает код, если кто-то попросит меня сделать так, чтобы основной цикл позволял другим потокам (или процессам) иметь некоторое процессорное время, на ум приходят два решения:
Опция 1
С готовностью вставьте паузу:
while( isValidState() ) {
execute();
sleep();
}
Вариант # 2
Выполнить переопределение:
void execute() {
super->execute();
sleep();
}
Этот код проще (поэтому его легче читать), чем цикл со встроенным switch
. isValidState
Метод должен определить , только если цикл должен быть продолжен. Рабочая лошадка метода должна быть абстрагирована в execute
метод, который позволяет подклассам переопределять поведение по умолчанию (сложная задача с использованием встроенного switch
и goto
).
Пример Python
Сравните следующий ответ (на вопрос Python), опубликованный на StackOverflow:
- Цикл навсегда.
- Попросите пользователя ввести свой выбор.
- Если пользователь вводит «перезапуск», продолжайте цикл бесконечно.
- В противном случае перестаньте зацикливаться навсегда.
- Конец.
Код
while True:
choice = raw_input('What do you want? ')
if choice == 'restart':
continue
else:
break
print 'Break!'
Против:
- Инициализировать выбор пользователя.
- Цикл, пока выбор пользователя - слово «перезапуск».
- Попросите пользователя ввести свой выбор.
- Конец.
Код
choice = 'restart';
while choice == 'restart':
choice = raw_input('What do you want? ')
print 'Break!'
Здесь while True
получается вводящий в заблуждение и чрезмерно сложный код.