Using Try/catch with Do/While
this is more of a conceptual question.
Is it aceptable/good programming mixing do/while loops with try/catch?
ex:
<?php
function main() {
$failure = 0;
do {
$failure += foo();
$failure += bar();
...
if ($failure) { return $failure; }
}
while ($failure == 0);
}
function foo() {
try {
echo 'DO FOO STUFF<br />';
return 0;
}
catch (Exception $e) {
return 1;
}
}
function bar() {
try {
echo 'DO BAR STUFF<br />';
return 0;
}
catch (Exception $e) {
return 1;
}
}
?>
The reason I'm asking is that I read somewhere that mixing both is bad practice. You should create your own exceptions and "throw" them instead. But isn't that a bit of an overkill?
EDIT: To explain the scenario where this question emerged, imagine a robot that has to follow a line. The rob开发者_如何学Pythonot calculates its position (X position, Y poistion, Z position and "postural" position) everytime he takes a step and sends the information to a server. Server doublechecks this information. If any anomaly is found, servers sends a "stop" signal to the robot. The robot stops, recalculates its position, resends information and waits for a "go" signal.
This loop example was based on the data feed received from the robot. If something went wrong, (like a broken wireless link, or an obstacle, or a misstep) the robot must stop to prevent going astray, or falling, or anything. We aren't interested in knowing what went wrong, or why it went wrong, just that it went wrong (or not). (that is actually taken care in another part of the code, not PHP based, the Debug Module).
EDIT 2: Like everyone pointed out, seems the right approach is to properly raise/handle the exceptions. Since everyone seems to agree in this, I don't know who to award the "right answer" tick. I will wait a few days and give it to the one with more votes if that's ok!
There is no reason to avoid mixing try/catch
with do/while
.
But the example you give has less problems with do/while
and more with swallowing exceptions in the try/catch
block.
Catching the base exception type and swallowing it is a bad practice in any language, PHP or otherwise. It is best to only catch specific exception types, and let the rest fall through the catch block.
For example, if you were accessing a file, and caught the FileNotFound
exception (if there is such a thing in PHP), that would be OK.
But if you catch all exception types, then you're going to catch things like OutOfMemoryException
. This would be fine, if you properly handled it, and made sure it wasn't going to throw again. But in your case, you're probably not "doing the right thing" for that case, so you should just let it fall through.
The reason you don't want to eat exceptions (without logging them) is that you won't be able to debug your code if it ever goes to a locked down production environment. If the exception is caught, then the user will just see buggy behavior, and won't be able to file a bug report that gives you enough information to debug it. They might be able to give you repro steps, but that is pretty unreliable. This is also pretty much worthless for an intermittant problem.
If you eat the exception, you're basically throwing away the most useful data there is for debugging.
Things that make this less true:
- Sometimes in top-level web code, you will want to catch the exception, log it, then swallow it so the user doesn't see it (but return from the function, so you don't execute more code while in a buggy state). This makes it so the user doesn't see revealing information about your code (the stack trace).
- If the language you are doing exception handling in has poor support for exceptions, and doesn't have derived exception types. I don't know a lot about PHP, so this may or may not be true in this language.
If you want to swallow the exceptions and just report the failure then this is okay. You'll have to do something like
$failure &= bar();
though, or you'll lose the failure condition of foo().
If you want to be able to act on the exception further up the call stack then you're better off leaving it alone, or at least rethrowing it, so you can catch it where you want to handle it.
There is no general reason to avoid using try/catch within functions called inside a do/while loop.
Depending upon what you are actually doing inside the loop you have the option of catching exceptions inside the loop, and exiting on an error condition returned, or wrapping the whole while loop in a try/catch block.
You should decide how to do it in any specific case according to what the exceptions mean for your code:
- Can the exception be recovered from?
- What action needs to be taken in response to an exception being thrown?
- What state should your program be left in after a particular exception has been thrown and handled?
In your example, bar()
will be executed even if foo()
generates an error. This may or may not be what you want. Catching exceptions outside the loop would not allow this option.
Also, the loop won't terminate when bar()
returns false
if foo()
subsequently returns true
- this is probably a bug. Catching any exceptions outside the loop would mean the loop would be terminated at the point of error. Again, this may or may not be desirable depending on your application.
Also, it is likely that different exceptions need to be handled in different ways. Importantly, if you catch the base exception type, rather than a more specific derived type you are losing the ability to do this. Catching more specific exceptions (including custom exceptions) will help you:
- Make sure you are not accidentally swallowing unexpected exceptions you didn't mean to catch.
- Have multiple different error scenarios handled by the same catch block (by throwing the same custom exception for each of those error scenarios).
精彩评论