Лучший рефакторинг для страшного цикла While (True) - PullRequest
13 голосов
/ 28 октября 2008

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

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

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

Ответы [ 12 ]

59 голосов
/ 28 октября 2008

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

start:

   // code goes here

goto start;

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

22 голосов
/ 28 октября 2008

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

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

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

22 голосов
/ 28 октября 2008

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

13 голосов
/ 28 октября 2008

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

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

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

12 голосов
/ 28 октября 2008

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

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

volatile bool m_shutdown = false;
void Run()
{
    while (!m_shutdown)
    { ... }
}
11 голосов
/ 28 октября 2008

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

Если это не сломано, не чините.

7 голосов
/ 28 октября 2008
#define ever 1
for (;ever;)

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

7 голосов
/ 28 октября 2008

Ситуация «работает вечно» иногда является частью большого конечного автомата. Многие встроенные устройства (с циклами run-forever) на самом деле не работают 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. Но мне нравится делать вид, что в какой-то будущей версии произойдет смена режима.

3 голосов
/ 28 октября 2008

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

3 голосов
/ 28 октября 2008

ошибка, рефакторинг .....

  • Замена бесконечного цикла бесконечной рекурсией :-)

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

...