April 02, 2004 Re: what is try-catch-finally? | ||||
---|---|---|---|---|
| ||||
On Fri, 2 Apr 2004 08:15:30 +1000, "Derek Parnell" <not@available.com> wrote: > "Karl Bochert" <kbochert@copper.net> wrote in message news:1103_1080855541@bose... > > On Thu, 01 Apr 2004 13:36:08 -0600, Brad Anderson <brad@dsource.dot.org> > wrote: > > > > > > > > > Karl Bochert wrote: > > > > > > > If complex error handling is needed, I would refactor or do something > > > like: > > > > try { > > > > if (err) { > > > > <pre_cleanup> > > > > throw <myerr> > > > > } > > > > } > > > > catchall { > > > > if (curerr == ioerr) <cleanup_io> > > > > else if (err == myerr ) <cleanup> > > > > else throw <curerr> > > > > } > > > > > > > > > in your example above, for 'try { }', the 'if (err) { }' portion is > > > built in. That's what try { } does, it automatically has a 'if (err) { > > > }'. The code to execute in the 'if (err) { }' is contained in the > > > 'catch (err) { }' block. > > > > Then I don't understand at all! > > Well, the way I think about it is that the 'try' phrase brackets the set of statements that I'm interested in trapping errors for. This could mean one, two, or any number of statements but the corresponding catch phrases will only get invoked if there is an error thrown for ANY of the bracketed statements. > > The 'finally' phrase collects together the cleanup code that is required for EVERY type of error rather than specific types of errors. If we didn't have the 'finally' option, then we would have to repeat code for specific type of error trapped. > > Something like ... > > try{ <whatever> } > catch(ioerr) { <commonCleanup> <ioCleanup>} > catch(myerr) { <commonCleanup> <myCleanup>} > catch(assertErr) { <commonCleanup> <assertCleanup>} > catch() { <commonCleanup> } > > rather than > > try{ <whatever> } > catch(ioerr) { <ioCleanup>} > catch(myerr) { <myCleanup>} > catch(assertErr) { <assertCleanup>} > finally {<commonCleanup>} > If those two are identical, then following the throw, the finally gets executed and then the catches get checked. I'm uncomfortable with 'out-of-order' flow control like that. So instead: try{ <whatever> } catch(myerr) { <common cleanup> } catch(ioerr) { <ioCleanup>} catch(myerr) { <myCleanup>} catch(assertErr) { <assertCleanup>} Though again, I would refactor first. > > If the common cleanup code was extensive, this could lead to a maintenance headache. > > >Some piece of code thows an error, and it only does so when there is an > error > > to thow. Therefore the 'if(err) throw' -- you don't want to throw if > there is no error. > > The above case is a little unusual (i think) in that the same function is > both throwing and catching its own error. > > (Thats all one function) > > The throw statement walks back the stack looking for a catch to handle it. > > If the 'finally' is meant to cleanup before the throw starts its walk, > then the cleanup can be inserted before the > > throw as above. Alternatively the thow could begin its walk at the > current subroutine, which could catch its > > own throw and cleanup there. either way, the finally clause is > superfluous. > > > > Why should there be a try clause? > > > > foo() > > { > > <code1> > > <code2> > > if (somethings_wrong) throw; > > <code3> > > catch { > > if (myerr) <cleanup and re-throw> > > } > > } > > The 'try' is used to explicitly define the set of statements that are associated with specific catch phrases. Without 'try' the compiler would not know which set of catch phrase to branch to when an error is thrown. > > Consider... > try{ > <code1> > <code2> > } > catch (myerror) { . . .} > <code3> > try { > <code4> > } > catch (errorX) { . . . } > I think that putting 2 try clauses in a routine is one of the last things I would do. Understanding the control flow for multiple kinds of errors in multilple sections of code is beyond me. Sort of spaghetti on steroids. Are you sure that this is not just a way to write the non-error code in a badly-structured form? > And now without 'try'. > > <code1> > <code2> > catch(myerror) { ... } > <code3> > <code4> > catch(errorX) { ... } > > The difference is that in the code with 'try', <code3> is not subject to any catch phrases, but in the code without 'try', one cannot see, or even do, that. Either way begs to be refactored. > > > Sometimes, when debugging, I put a try/catch on each statement to find some bugs. Especially 'access violation' ones. > > try{ <code1> } catch {printf("DEBUG A\n");} > try{ <code2> } catch {printf("DEBUG B\n");} > try{ <code3> } catch {printf("DEBUG C\n");} > try{ <code4> } catch {printf("DEBUG D\n");} > try{ <code5> } catch {printf("DEBUG E\n");} > > Nasty, but it does help. Of course it would be nice to have 'access violation' messages give a file and line number ;-) > > > > What does putting <code2> and the throw in a try clause accomplish? > > > > > > > > > > > Come to think of it, what does 'try' accomplish? > > > > > > > > > I have found that once I got used to the try-catch-finally, it's like cocaine (You can't do without it). It helps you get closer to bullet-proof code. > > > > > Perl programmers say the same thing about all manner of obfuscatory > features :-) > > As to Bach coders too, I believe... As to C++, D, php etc, coders too, then. (BTW, there aren't any Bach coders!) To quote from the introduction of 'Effective Perl Programming' "You may reach a point at which yo want to move beyond plain, direct and verbose Perl toward something more succinct and individualistic." ;-) Perhaps I'm warped by a bit of experience with Java? A minority of 1 Karl Bochert |
Copyright © 1999-2021 by the D Language Foundation