Приміщення
Наступний код слід вважати поганою формою, незалежно від мови та бажаної функціональності:
while( true ) {
}
Підтверджуючі аргументи
while( true )
Петля погана форма тому , що він:
- Розриває мається на увазі контракт циклу на час.
- У оголошенні циклу while слід чітко вказати єдину умову виходу.
- Мається на увазі, що це петля назавжди.
- Код у циклі повинен бути прочитаний, щоб зрозуміти закінчення.
- Цикли, які повторюються назавжди, заважають користувачеві закінчувати програму всередині програми.
- Неефективна.
- Існує кілька умов припинення циклу, включаючи перевірку на "справжню".
- Схильний до помилок.
- Не можна легко визначити, куди слід поставити код, який завжди буде виконуватися для кожної ітерації.
- Приводить до зайвого складного коду.
- Автоматичний аналіз вихідного коду.
- Для пошуку помилок, аналізу складності програми, перевірок безпеки або автоматичного отримання будь-якої іншої поведінки вихідного коду без виконання коду, уточнення початкових умов порушення дозволяє алгоритмам визначати корисні інваріанти, тим самим покращуючи показники автоматичного аналізу вихідного коду.
- Нескінченні петлі.
- Якщо всі завжди використовують
while(true)
для циклів, які не є нескінченними, ми втрачаємо здатність стисло спілкуватися, коли петлі насправді не мають умови завершення. (Можливо, це вже сталося, тому справа в суперечці.)
Альтернатива "Перейти"
Наступний код є кращою формою:
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
призводять до оманливого і надмірно складного коду.