提问人:Jeff Schumacher 提问时间:10/29/2008 最后编辑:Jeff Schumacher 更新时间:9/28/2019 访问量:17228
可怕的 While (True) 循环的最佳重构
Best refactoring for the dreaded While (True) loop
问:
如果你像我一样,在While(True)循环的现场瑟瑟发抖,那么你也一定已经认真思考了重构它的最佳方法。我见过几种不同的实现,没有一个比其他任何实现都好,比如计时器和委托组合。
那么,你想出或看到的重构可怕的 While (True) 循环的最佳方法是什么?
编辑:正如一些评论所提到的,我的意图是让这个问题成为一个“无限循环”重构,例如运行一个 Windows 风格的服务,其中唯一的停止条件是 OnStop 或致命的异常。
答:
这有什么可怕的?尝试找到一个常见的中断条件,并将其重构为循环的头部。如果这是不可能的——很好。
评论
将 True 替换为要用于跳出循环的条件。
对于服务或后台线程,可以使用:
volatile bool m_shutdown = false;
void Run()
{
while (!m_shutdown)
{ ... }
}
评论
errr,要进行重构.....
- 将无限循环替换为无限递归 :-)
好吧,如果你有一种支持 Tail 调用的语言......
当我遇到 while(true) 循环时,它会告诉我
- 在回路的顶部(或底部)不容易测试断裂条件,
- 有多种断裂条件,
- 或者之前的程序员懒得正确地分解循环。
1 和 2 表示您不妨坚持使用 while(true)。(我用 ,但在我看来,这是一种风格。我和另一张海报在一起,为什么要害怕这个?我害怕被折磨的循环,它们跳过箍以“正确”滚动循环。for(;;)
如果你想让它无限期地持续下去,直到程序流完全流产,我看不出while(true)有什么问题。我最近在 .NET 数据收集服务中遇到了它,该服务将 while (true) 与 thread.sleep 相结合,每分钟唤醒一次并轮询第三方数据服务以获取新报告。我考虑过用计时器和委托重构它,但最终决定这是最简单、最容易阅读的方法。10 次中有 9 次是清晰的代码气味,但是当没有退出条件时,为什么要让事情变得更加困难?
“永远运行”的情况有时是更大的状态机的一部分。许多嵌入式设备(具有永远运行循环)并不是真正永远运行。它们通常具有多种操作模式,并将在这些模式之间排序。
当我们构建热泵控制器时,有一个运行了一段时间的自检电源 (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;)
?
嗯,就让它保持原样,而(真实)可能和你将要得到的一样清晰。
评论
for(;"ever";)
我的偏好是
start:
// code goes here
goto start;
这最清楚地表达了意图。祝你好运,让它通过你的编码标准。(想知道这会让我付出多少业力)。
评论
while(true)
goto
while (true)
我们真的需要重构while(true)循环吗? 有时它是一种编码标准,大多数开发人员已经习惯了这种结构。如果你必须认真思考如何重构这段代码,你确定重构它是个好主意吗?
Goto曾经是编码标准中的害群之马。我遇到过 goto 使代码更具可读性和更短的算法。有时不值得重构(或者最好使用 goto)。
另一方面,大多数时候你可以避免while(true)。
void whiletrue_sim(void)
{
//some code
whiletrue_sim();
}
警告:您的堆栈可能会溢出。
评论