Fortify Your Loops
This is another post in a continuing, yet oddly sporadic, series of entries on building reliable software. Here's another outrageous tenet of my philosophy:
Yes, that's right: ban the while loop. Get rid of any while loops in your code. Today. Here's why.
Consider the following, oh-so-typical code:
myQuery.FetchFirst(); while (!myQuery.IsEndOfFile()) { ... processing steps ... myQuery.FetchNext(); } |
What's wrong with that? Nothing you say? Au contraire, mon frere. Consider the jamoke who comes after you and adds some additional logic, like so:
myQuery.FetchFirst(); while (!myQuery.IsEndOfFile()) { ... processing steps ... if (bSkipRecord) { continue; } ... processing steps ... myQuery.FetchNext(); } |
Guess what? If the boolean bSkipRecord ever gets set, you're in infinite-loop-land and you might as well go out for coffee and a cigarettes -- indefinitely -- while this code runs and runs and runs... basically like the Energizer Bunny plugged into a 220-volt outlet.
So, what do we do in cases like this instead of a while loop? Basically, fortify all of your loops. Make them into for loops.
for (myQuery.FetchFirst(); !myQuery.IsEndOfFile(); myQuery.FetchNext()) { ... processing steps ... if (bSkipRecord) { continue; } ... processing steps ... } |
Now when Einstein adds his logic, we no longer have the catastrophic result of the system hanging (or an internal denial-of-service attack, as I like to call it).
Going a step further, we can fail-safe the loop. By "fail-safing", I mean assigning a maximum number of loop iterations and recording an error if we hit that maximum. This serves two purposes: to short-circuit a possible infinite loop and to detect the fact that the loop constraint did not work as intended.
for (ixCount = 0, myQuery.FetchFirst(); !myQuery.IsEndOfFile() && ixCount < MAX_TBL_COUNT; myQuery.FetchNext(), ixCount++) { ... processing steps ... if (bSkipRecord) { continue; } ... processing steps ... } if (ixCount >= MAX_TBL_COUNT) { // Note that our loop did not work as intended! } |
So, I guess we can boil this lesson down to two tenets: (a) fortify your loops; and (b) fail-safe your loops.
Không có nhận xét nào:
Đăng nhận xét