Prev: Deriving from a class derived from a CDialog
Next: How to show underlined menu shortcut letters by default for a contextmenu ?
From: Goran on 23 Jun 2010 03:08 On Jun 22, 9:14 pm, "Doug Harrison [MVP]" <d...(a)mvps.org> wrote: > On the API designer side, using > exceptions where return codes are more appropriate forces callers to write > try/catch whenever they use the function, so that's a bad use of > exceptions. Hey! Tell that to designers of APIs like VCL of Borland or .NET, then ;-). On a more serious note... .NET almost exclusively uses exceptions to report errors and I am aware of one place where, over the time, they decided to revert to having a non-throwing variant of the function (TryParse wasn't there in initial .NET versions). > You never want to turn exception usage into a clumsier version > of return codes. That is true. What I wanted to say, I guess, is that even API design goes well with exceptions, and APIs where it is interesting to have error-return seem rarer than what one might think from your post. Goran.
From: Goran on 23 Jun 2010 03:15 On Jun 22, 11:06 pm, "David Ching" <d...(a)remove-this.dcsoft.com> wrote: > "Doug Harrison [MVP]" <d...(a)mvps.org> wrote in messagenews:9c1226ldk8g207f4asif27nehrcfji6g0e(a)4ax.com... > > > > > On Tue, 22 Jun 2010 13:12:33 -0400, Joseph M. Newcomer > > <newco...(a)flounder.com> wrote: > > >>I'm not sure this is a good piece of advice. I use try/catch a lot; it is > >>essentially a > >>"non-local GOTO", a structured way of aborting execution and returning to > >>a known place, > >>while still guaranteeing that all intermediate destructors for stack > >>variables are called. > >>It is particularly useful in writing tasks like recursive-descent parsers > >>(particularly if > >>you just want to stop without trying to do error recovery, which is always > >>hard) and > >>terminating threads while still guaranteeing that you return from the > >>top-level thread > >>function. It is clean and well-structured way of aborting a > >>partially-completed > >>operation. An it is the only way to report errors from operations like > >>'new'. Also, look > >>at the number of exceptions that can be thrown by std:: or boost::. > > > Goran was not saying exceptions are bad, just that overly frequent use of > > try/catch is bad, which it usually is. I've been saying for a long long > > time that there's an inverse relationship between the number of try/catch > > clauses you have and the effectiveness with which you're using exceptions. > > There are a number of reasons for this. On the API designer side, using > > exceptions where return codes are more appropriate forces callers to write > > try/catch whenever they use the function, so that's a bad use of > > exceptions. You never want to turn exception usage into a clumsier version > > of return codes. On the user side, try/catch gets overused when people > > don't employ the RAII idiom and need to perform clean-up that should be > > handled by a destructor. Ideally, exceptions are caught far away from > > where > > they're thrown, in a top-level handler, which reports the error to the > > user, logs it, or whatever. It is relatively rare for well-designed code > > to > > need to handle the exception closer to the throw-point. > > Not to mention, the overhead of throwing exceptions reduces performance if > many exceptions are thrown. I am sorry, I have to press you here. When did you have performance issues because of that? The thing is, if there's too many exceptions thrown, there is something wrong with the design. Also, if there indeed is too many of them, chances are that the code doesn't work anyhow. If that's the case, does it really matter how fast (or slow) it doesn't work? You need e.g. some multithreaded code where some threads eat up too much time because it doesn't work at all and throws exceptions in a loop. IOW, situations where one will be concerned about performance aspect of exceptions are much rarer than one might think from your post. ( I am getting annoying with this, aren't I? :-( ) Goran.
From: Goran on 23 Jun 2010 03:18 On Jun 23, 1:49 am, Joseph M. Newcomer <newco...(a)flounder.com> wrote: > Key here is how much you have to do in the catch. Putting all the recovery code in the > catch would consolidate it and eliminate that horror of "goto exit" that happens so often. Hey, +1 for this. goto is for me forbidden in C++ (but arguably the best approach for the likes of C). Goran.
From: Giovanni Dicanio on 23 Jun 2010 04:37 On 23/06/2010 01:51, Joseph M. Newcomer wrote: > Note that this could be handled as > > BOOL TryParse(...args...) > { > try > { > Parse(...); > return TRUE; > } > catch(..whatever..) > { > return FALSE; > } > } > > It ain't rocket science. And it isn't clear to me how handling the exception results in > "bad code". Sure it isn't (ain't?) rocket science... but do you like a fopen that throws an exception if the file cannot be opened? No, I prefer one returning an error code. The fact that you can't open a file is not an exceptional condition, and I prefer code like: if ( some_open_file_api(...) == error ) { ... do what you want... (e.g. create the file, or other stuff...) } ... normal flow instead of try/catch. It was clearly written before: the usefulness of exceptions is inversely proportional to the number of try/catch you use: if you clutter your code with lots of try/catch then IMHO you are overusing (abusing) exceptions. I think exceptions should be used in *exceptional* conditions (like David wrote before). BTW: I like these articles from the OldNewThing blog: "Cleaner, more elegant, and wrong" http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx "Cleaner, more elegant, and harder to recognize" http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx Giovanni
From: Giovanni Dicanio on 23 Jun 2010 04:42
On 23/06/2010 06:17, David Ching wrote: > Joe, all I know is the MS architects felt adding TryParse() was > necessary in .NET 2.0 due to the overhead of Parse() throwing > exceptions. You can take it up with them. I do agree with the addition of TryParse: "Vexing exceptions" http://blogs.msdn.com/b/ericlippert/archive/2008/09/10/vexing-exceptions.aspx <quote> Vexing exceptions are the result of unfortunate design decisions. Vexing exceptions are thrown in a completely non-exceptional circumstance, and therefore must be caught and handled all the time. The classic example of a vexing exception is Int32.Parse, which throws if you give it a string that cannot be parsed as an integer. But the 99% use case for this method is transforming strings input by the user, which could be any old thing, and therefore it is in no way exceptional for the parse to fail. Worse, there is no way for the caller to determine ahead of time whether their argument is bad without implementing the entire method themselves, in which case they wouldn't need to be calling it in the first place. This unfortunate design decision was so vexing that of course the frameworks team implemented TryParse shortly thereafter which does the right thing. You have to catch vexing exceptions, but doing so is vexing. Try to never write a library yourself that throws a vexing exception. </quote> Giovanni |