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

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

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

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

Ответы

Ответ 1

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

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

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

Ответ 2

Мое предпочтение было бы

start:

   // code goes here

goto start;

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

Ответ 3

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

Ответ 4

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

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

1 и 2 означает, что вы можете также придерживаться while (true). (Я использую for(;;), но это вещь стиля, на мой взгляд.) Я с другим плакатом, зачем этого бояться? Я боюсь чередующихся петель, которые прыгают через обручи, чтобы получить петлю "правильно".

Ответ 5

Замените True условием, которое вы собираетесь использовать, чтобы выйти из цикла.

В случае службы или фонового потока вы можете использовать:

volatile bool m_shutdown = false;
void Run()
{
    while (!m_shutdown)
    { ... }
}

Ответ 6

Почему рефакторинг? И что такое "ужасно" в этой конструкции? Он широко используется и хорошо понимается.

Если он не сломался, не исправляйте его.

Ответ 7

"Бегущая навсегда" ситуация иногда является частью более крупного конечного автомата. Многие встроенные устройства (с циклами run-forever) на самом деле не запускают навсегда. Они часто имеют несколько режимов работы и будут переключаться между этими режимами.

Когда мы построили контроллеры теплового насоса, был режим включения питания (POST), который работал некоторое время. Затем был предварительный режим экологического сбора, который работал, пока мы не выяснили все зоны и термостаты, а что - нет.

Некоторые инженеры утверждали, что следующим был цикл "run-forever". Это было не так просто. На самом деле было несколько режимов работы, которые перевернулись и плюхнулись. Был нагрев, размораживание, охлаждение, холостой ход и прочее.

Мое предпочтение заключается в том, чтобы обрабатывать цикл "навсегда", как реально только один рабочий режим - в какой-то момент в будущем могут быть другие.

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. Но мне нравится притворяться, что в какой-то будущей версии будет изменение режима.

Ответ 8

#define ever 1
for (;ever;)

?

Мех, просто оставьте это как есть, тогда как (правда), вероятно, так же разборчиво, как вы собираетесь получить.

Ответ 9

errr, чтобы быть рефакторингом.....

  • Замените бесконечную петлю бесконечной рекурсией:-)

Хорошо, если у вас есть язык, поддерживающий Tail calls....

Ответ 10

Если вы хотите, чтобы он продолжался бесконечно до полного прерывания потока программы, я пока не вижу ничего плохого (true). Недавно я столкнулся с этим сервисом сбора данных .NET, который комбинировал while (true) с thread.sleep, чтобы каждую минуту просыпаться и опросить стороннюю службу данных для новых отчетов. Я рассмотрел рефакторинг с таймером и делегатом, но в конечном итоге решил, что это самый простой и простой способ чтения. В 9 раз из 10 это чистый запах кода, но когда нет условия выхода, зачем делать вещи более трудными?

Ответ 11

Я не против, когда бесконечный цикл содержится в окне и умирает с окном.

Подумайте о рекурсии Хассельхоффа.

Ответ 12

void whiletrue_sim(void)
  {
    //some code
    whiletrue_sim();
  }

Предупреждение. Ваш стек может быть переполнен.