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

StackOverflow https://stackoverflow.com/questions/244445

  •  04-07-2019
  •  | 
  •  

Вопрос

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

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

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

Это было полезно?

Решение

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

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

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

Другие советы

Мое предпочтение было бы следующим

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)
    { ... }
}

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

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

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

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

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

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

#define ever 1
for (;ever;)

?

Meh, просто оставьте все как есть, в то время как (true), вероятно, настолько разборчиво, насколько вы собираетесь получить..

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

  • Замените Бесконечный цикл Бесконечной Рекурсией :-)

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top