恐ろしいWhile(True)ループの最適なリファクタリング
-
04-07-2019 - |
質問
私と同じように、While(True)ループの場所で震えているなら、あなたもそれをリファクタリングする最善の方法について長く一生懸命考えたに違いありません。いくつかの異なる実装を見てきましたが、タイマー&など、他のどの実装よりも優れているものはありません。デリゲートの組み合わせ。
では、恐ろしいWhile(True)ループをリファクタリングするためにあなたが思いついた、または見た最良の方法は何ですか?
編集:いくつかのコメントが述べたように、私の質問はこの質問を「無限ループ」にすることでした。リファクタリング。たとえば、停止条件がOnStopまたは致命的な例外のみであるWindowsスタイルのサービスを実行します。
解決
本当に while(true)ループをリファクタリングする必要がありますか? 時々それはコーディング標準であり、ほとんどの開発者はこの構造に慣れています。このコードをリファクタリングする方法について一生懸命に考えなければならない場合、それをリファクタリングするのは良い考えだと確信していますか?
Goto は、コーディング標準の黒羊でした。 goto がコードをより読みやすく、短くしたアルゴリズムに出会いました。リファクタリングする価値がない場合があります(または goto を使用した方がよい場合があります)。
一方で、ほとんどの場合 while(true)を回避できます。
他のヒント
私の好みは
start:
// code goes here
goto start;
これは意図を最も明確に表しています。コーディング基準を超えて幸運を祈ります。 (これがどれくらいのカルマに私を犠牲にするだろうか。)
何がそんなに恐ろしいのですか?一般的なブレーク条件を見つけて、ループの先頭になるようにリファクタリングしてください。それが不可能な場合–罰金。
while(true)ループが発生すると、次のいずれかがわかります
- ループの上部(または下部)でブレーク条件を簡単にテストできません。
- 複数のブレーク条件があります、
- または前のプログラマーが面倒でループを適切に分解できませんでした。
1および2は、while(true)に固執することを意味します。 (私は for(;;)
を使用していますが、それは私の意見ではスタイルのことです。)私は別のポスターと一緒にいます、なぜこれを恐れるのですか?ループを「適切に」ロールバックするためにフープを飛び越える拷問されたループを恐れています。
Trueを、ループから抜け出すために使用する条件に置き換えます。
サービスまたはバックグラウンドスレッドの場合、次を使用できます。
volatile bool m_shutdown = false;
void Run()
{
while (!m_shutdown)
{ ... }
}
リファクタリングする理由そして、何がそんなに「恐ろしい」のかこの構造について?広く使用されており、よく理解されています。
破損していない場合は、修正しないでください。
「永遠に続く」状況は、より大きな状態マシンの一部である場合があります。多くの組み込みデバイス(永久実行ループ)は、実際には永久に実行しません。多くの場合、いくつかの動作モードがあり、それらのモード間でシーケンスが行われます。
ヒートポンプコントローラーを構築したとき、しばらく実行されていたPOST(POST)モードがありました。それから、すべてのゾーンとサーモスタットとその他を理解するまで実行された予備的な環境収集モードがありました。
一部のエンジニアは、次に来るのは「永遠に走る」ことだと主張しました。ループ。それほど単純ではありませんでした。実際には、いくつかの動作モードが反転および反転しました。暖房、霜取り、冷却、アイドリングなどがありました。
私の好みは、「永遠に」を扱うことです。本当に1つの動作モードとしてループします-将来のある時点で他のモードが存在する可能性があります。
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;)
?
まあ、そのままにしておきますが、(true)はおそらくあなたが理解しようとしているのと同じくらい読みやすいです。
errr、リファクタリングのため.....
- 無限ループを無限再帰に置き換える:-)
まあ、もしあなたがテールコールをサポートする言語を持っているなら...
プログラムフローが完全に中断されるまで無期限に継続したい場合、while(true)に問題はありません。最近、.NETデータ収集サービスで遭遇しました。while(true)とthread.sleepを組み合わせて、毎分起動し、サードパーティのデータサービスをポーリングして新しいレポートを探しました。タイマーとデリゲートを使用してリファクタリングすることを検討しましたが、最終的にこれが最も簡単で読みやすい方法であると判断しました。 10回のうち9回は明確なコードの匂いですが、終了条件がない場合、なぜ物事を難しくするのですか?
ウィンドウ内に無限ループが含まれていて、ウィンドウで死ぬときは気にしません。
ハッセルホフの再帰を考えてください。
void whiletrue_sim(void)
{
//some code
whiletrue_sim();
}
警告:スタックは、言語、オプティマイザーなどに依存してオーバーフローする可能性があります。