Лучший рефакторинг для страшного цикла While (True)

Если, как я, вы дрожать на месте While (True) цикла, то вы тоже должны подумать, долго и упорно о лучшем способе рефакторинга, рефакторинга его. Я видел несколько разных реализаций, ни одна из которых не была лучше, чем любая другая, например комбинация таймера и делегата.

Так каков наилучший способ, которым вы придумали или видели, чтобы реорганизовать страшный цикл "Пока" ("Истина")?

Редактировать: Как уже упоминалось в некоторых комментариях, я хотел, чтобы этот вопрос был рефакторингом с "бесконечным циклом", таким как запуск службы в стиле Windows, где единственными условиями остановки были бы OnStop или фатальное исключение.

12 ответов

Решение

Нужно ли нам реорганизовывать циклы while(true)? Иногда это стандарт кодирования, и большинство разработчиков привыкли к этой структуре. Если вам нужно серьезно подумать о том, как реорганизовать этот код, вы уверены, что это хорошая идея, чтобы реорганизовать его?

Гото раньше был паршивой овцой в стандартах кодирования. Я встречал алгоритмы, где goto сделал код намного более читабельным и коротким. Иногда не стоит проводить рефакторинг (или лучше использовать goto).

С другой стороны, вы можете избежать, пока (правда) большую часть времени.

Мое предпочтение будет

start:

   // code goes here

goto start;

Это наиболее ясно выражает намерение. Удачи в преодолении ваших стандартов кодирования. (Интересно, сколько мне будет стоить карма).

Что такого страшного в этом? Попробуйте найти общее условие разрыва и рефакторинг, чтобы он стал главой цикла. Если это невозможно - хорошо.

Когда я сталкиваюсь с циклом while(true), это говорит мне либо

  1. условие разрыва нелегко проверить в верхней (или нижней) части цикла,
    • Есть несколько условий перерыва,
    • или предыдущий программист был слишком ленив, чтобы правильно разложить цикл.

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();
  }

Предупреждение: ваш стек может быть переполнен, в зависимости от языка, оптимизатора и других вещей.

Другие вопросы по тегам