Лучший рефакторинг для страшного цикла While (True)
Если, как я, вы дрожать на месте While (True) цикла, то вы тоже должны подумать, долго и упорно о лучшем способе рефакторинга, рефакторинга его. Я видел несколько разных реализаций, ни одна из которых не была лучше, чем любая другая, например комбинация таймера и делегата.
Так каков наилучший способ, которым вы придумали или видели, чтобы реорганизовать страшный цикл "Пока" ("Истина")?
Редактировать: Как уже упоминалось в некоторых комментариях, я хотел, чтобы этот вопрос был рефакторингом с "бесконечным циклом", таким как запуск службы в стиле Windows, где единственными условиями остановки были бы OnStop или фатальное исключение.
12 ответов
Нужно ли нам реорганизовывать циклы while(true)? Иногда это стандарт кодирования, и большинство разработчиков привыкли к этой структуре. Если вам нужно серьезно подумать о том, как реорганизовать этот код, вы уверены, что это хорошая идея, чтобы реорганизовать его?
Гото раньше был паршивой овцой в стандартах кодирования. Я встречал алгоритмы, где goto сделал код намного более читабельным и коротким. Иногда не стоит проводить рефакторинг (или лучше использовать goto).
С другой стороны, вы можете избежать, пока (правда) большую часть времени.
Мое предпочтение будет
start:
// code goes here
goto start;
Это наиболее ясно выражает намерение. Удачи в преодолении ваших стандартов кодирования. (Интересно, сколько мне будет стоить карма).
Что такого страшного в этом? Попробуйте найти общее условие разрыва и рефакторинг, чтобы он стал главой цикла. Если это невозможно - хорошо.
Когда я сталкиваюсь с циклом while(true), это говорит мне либо
- условие разрыва нелегко проверить в верхней (или нижней) части цикла,
- Есть несколько условий перерыва,
- или предыдущий программист был слишком ленив, чтобы правильно разложить цикл.
1 и 2 означает, что вы можете придерживаться while(true). (Я использую for(;;)
, но это стиль, по моему мнению.) Я с другим постером, зачем бояться этого? Я боюсь замкнутых петель, которые прыгают через обручи, чтобы петля катилась "правильно".
Почему рефакторинг? И что же такого "ужасного" в этой конструкции? Он широко используется и хорошо понят.
Если это не сломано, не исправляйте это.
Замените True условием, которое вы собираетесь использовать, чтобы выйти из цикла.
В случае служебного или фонового потока вы можете использовать:
volatile bool m_shutdown = false;
void Run()
{
while (!m_shutdown)
{ ... }
}
Ситуация "работает вечно" иногда является частью более крупного конечного автомата. Многие встроенные устройства (с циклами run-forever) на самом деле не работают вечно. Они часто имеют несколько режимов работы и будут последовательно переключаться между этими режимами.
Когда мы создавали контроллеры тепловых насосов, в течение некоторого времени работал режим самотестирования при включении питания (POST). Затем был предварительный режим сбора окружающей среды, который работал, пока мы не выяснили все зоны и термостаты и что-нет.
Некоторые инженеры утверждали, что последующим этапом стал цикл "беги навсегда". Это было не так просто. На самом деле было несколько режимов работы, которые переключались и колебались. Там было отопление, разморозка, охлаждение, холостой ход и прочее.
Я предпочитаю трактовать "вечный" цикл как действительно один рабочий режим - в будущем могут появиться другие.
someMode= True
while someMode:
try:
... do stuff ...
except SomeException, e:
log.exception( e )
# will keep running
except OtherException, e:
log.info( "stopping now" )
someMode= False
При некоторых обстоятельствах ничего, что мы видели до сих пор, не устанавливает someMode
в False
, Но мне нравится делать вид, что в какой-то будущей версии произойдет смена режима.
#define ever 1
for (;ever;)
?
Мех, просто оставь все как есть, в то время как (правда), вероятно, так же разборчиво, как ты собираешься получить..
Ошибаться, быть рефакторингом.....
- Замените бесконечный цикл на бесконечную рекурсию:-)
хорошо, если у вас есть язык, который поддерживает вызовы Tail....
Если вы хотите, чтобы это продолжалось бесконечно до полного прерывания потока программы, я не вижу ничего плохого в while (true). Я столкнулся с этим недавно в сервисе сбора данных.NET, который в сочетании с (true) и thread.sleep просыпался каждую минуту и опрашивал стороннюю службу данных на наличие новых отчетов. Я подумал о рефакторинге с помощью таймера и делегата, но в итоге решил, что это самый простой и легкий для чтения метод. 9 раз из 10 это чистый запах кода, но когда нет условий выхода, зачем усложнять ситуацию?
Я не против, когда бесконечный цикл содержится в окне и умирает вместе с окном.
Вспомните рекурсию Хассельхоффа.
void whiletrue_sim(void)
{
//some code
whiletrue_sim();
}
Предупреждение: ваш стек может быть переполнен, в зависимости от языка, оптимизатора и других вещей.