From: "Carlo E. Prelz" Date: 2012-11-17T16:40:46+09:00 Subject: Re: Question on exceptions Subject: Re: Question on exceptions Date: Sat 17 Nov 12 12:47:06PM +0900 Quoting tamouse mailing lists (tamouse.lists@gmail.com): > Do you (or anyone else who'd like to chime in!) have a ... set of > heuristics, maybe? .. that help you know when it's appropriate and > when it's not? > > The reason I ask is not merely academic. I see in code many places > where it is raising and exception, and then the rescue code does > something like this: > > rescue Exception > > # blah blah > > end > > In other words, they know an exception might be raised, but they trap > evey possible exception, rather than a specific one. I'm worried (?) > (thinking) that use of raising exceptions might be a little too easily > decided upon as the answer, and if I should maybe push back on such > implementations... I will try to describe in words the fuzzy logic I follow. I do not often use exceptions. In more than seven years of using Ruby, I have probably only subclassed Exception once or twice. I generally capture an exception (thrown by my code or by other libraries) like this: rescue => err print_a_message_on_the_log(err) maybe_print_backtrace(err.backtrace) maybe_correct_this_or_that_value maybe_break_out_of_a_loop_or_return end The Ruby interpreter's usage of exceptions is mostly limited to grave events. I try to mimic this usage in my raising practices. Basically, exceptions should only indicate situations that have to be debugged out: an exception should never indicate a special, but acceptable, case. I come from C (I still use C). Practice in C tends to be that your procedures return non-zero in case of errors - the non-zero value indicates the type of error. This can be cascaded: you check the return value, and return the same if negative, and so on. But it can certainly escalate to awkwardness, especially if at some level your function has to return other data. For me, the advantage of the exception mechanism is that it has its own, separate distribution channel. If you do not catch an exception, the program terminates, with VERY useful debugging data: the message of the exception, and the backtrace. When I encounter an exception, the catching option is not the preferred one. If at all possible, I try to modify the code so that the special case either does not happen, or is specifically handled, in a programmatic way. If I resort to a rescue clause like the one above, it means that I come to the (maybe temporary) conclusion that the special case can happen, but it is something to be monitored. My programs tend to have meaningful log files: disk space is cheap. Patterns of repetition of warning messages may give precious hints to solving complex bugs or refactoring non-optimized algorithms. If I catch an exception, I can do so at any of the steps of the backtrace. Often it is useful to make use of the exception-raising logic to get out of some of the levels of the call tree. This iterative process is part and parcel of the testing phase that all new code has to undergo. Every situation is different. If you really care about the healthy operation of your code, every choice should be tuned to the specific case. The process cannot be made automatic. Automatic coding/debugging results in mediocre programs. In all cases, I would not use the exception mechanism in the example that the original poster makes. Rather, the BankAccount#withdraw method would return true (or possibly the new balance of the account) if the withdraw method was successful, and false otherwise. Ruby has a neat syntax for catching false/nil values: unless(account.withdraw(sum)) ... The condition of insufficient funds is maybe undesirable from the point of view of the account holder, but it is a perfectly legitimate situation; all mechanisms that handle withdrawals should foresee and properly manage it. Withdrawals *can* fail. It should not be an exception-al event from the point of view of the code. This is just an effort to put into words my craft. Every other craftsman/woman will most probably follow different ways. Carlo -- * Se la Strada e la sua Virtu' non fossero state messe da parte, * K * Carlo E. Prelz - fluido@fluido.as che bisogno ci sarebbe * di parlare tanto di amore e di rettitudine? (Chuang-Tzu)