views:

254

answers:

5

This question got me thinking about the ratio between the number of exception throw sites and the number of try blocks in my own code. A swift grep on a couple of non-library projects indicated it is something like 150 throws to 1 try. This kind of surprised me - I was expecting something like 50 to 1 - and I wondered if others would like to share approximate figures here.

And a supplementary question - if you were setting down some coding guidelines, what would an "ideal" ratio be?

+4  A: 

I don't have any numbers to give, but if I were to set up a coding guideline, I would say it should be generally quite a bit less than that, say 15-to-1. My argument is that an exception should be exceptional and specific. How can you possibly handle 50 different error conditions in 1 place? I understand that some of them are actually the same error, but that still seems high.

Both projects are command line programs which basically always fail if an exception occurs, with a diagnostic of course. It seems I never use exceptions to check status in these. It would be interesting to compare this with my code for server apps, but unfortunately all the servers of any complexity (which could not behave like this) that I've written have been for clients, and I don't own the code. I was hoping that SO users could provide the missing info, but it is not looking likely :-(
anon
A: 

0/0 is an undefined number. :-)

zvrba
So you use `new (std::nothrow)` everywhere?
GMan
@GMan: I suppose it depends on the way the question is interpreted. I interpreted it as "what is the ratio of throw expressions to try blocks?" and not "what is the ratio of statements that might throw to try blocks?" Metrics for the latter case would be near impossible to compute. "0/0" makes sense for the former case.
James McNellis
@James I've just voted this answer up (don't see a reason for the downvote) but I guess the ratio in all C++ programs should really be a minimum of 1 try to unknown throws.
anon
I downvoted this answer because "this answer is not useful." Without any details (e.g., what type of project is this? Is this a toy project or real-world software? Does it use libraries or implementation facilities that might throw?) the answer is not helpful; no conclusion can be made about the meaning of this data point.
James McNellis
+3  A: 

In my current hobby project (an implementation of a C and C++ preprocessor), there are currently 293 throw expressions and two try blocks.

Effectively, it's written such that an exception is thrown whenever an unrecoverable error occurs, and there isn't much in the way of error recovery (at least at the moment).

I've been playing around a bit with using a form of Scope Guard with a diagnostic handler to accumulate detailed error information as the stack is unrolled, but haven't yet decided whether it is useful enough or practical to use in production code.

James McNellis
Thanks - spookily similar to my figure!
anon
@James: I'd really like to know more about this Scope Guard idea. I've had a similar idea a while ago, but was afraid that MultiThreading + the possibility of multiple exceptions at once (since you can throw from within a `catch`) would screw me and never pushed further.
Matthieu M.
@Matthieu: Sure. I'll try and post something this week and will let you know. My biggest concern right now is that it's more invasive than I'd like (to avoid globals, everything has a reference to the diagnostic handler; there are pros and cons to that).
James McNellis
That's the issue I faced when mentioning MultiThreading in fact, passing handlers each time is a bother (and needlessly complicates the signature of the function, obfuscating its purpose), yet globals... well, we all know how evil those are :x
Matthieu M.
+1  A: 

I think that the ratio is wholly meaningless. I might structure, say, a compiler, by throwing compilation errors as exceptions, and using one try to log the exception and abort compilation. In that instance, I might have one try to catch every single possible compilation error, which may be an exceedingly large number (e.g., a C++ compiler/linker/preprocessor) or very few (my Brainfuck interpreter).

The quantity of situations that can be handled identically is entirely application dependent.

Fundamentally, the fact that one try may catch an infinite number of throws suggests to me that you would need contextual data to even suggest that any given ratio is good, bad, or anything else, hence, application dependent.

In addition, grep will not demonstrate this to you. There's many throws that exist, even though realistically if such a thing occurs, you won't be able to recover. For example, you could suggest that operator new might throw a std::bad_alloc on Windows if you hit the virtual address limit, and count that as a throw. However, in reality, I would never catch such an exception- I don't know of any meaningful way to recover from such an exception. You would have to check out every throw and it's corresponding catch.

DeadMG
This is very common in my language-based projects: one try, many throws.
Jon Purdy
Without figures it is hard to say if the ratio is meaningless. The two people (me and James) who bothered to make a measurement rather than spouting off on the subject came up with near identical figures. Is this significant? Almost certainly not, but without some base of quantitative data, all opinions must have equal worth - i.e. none.
anon
Opps, three - sorry Georg. But I guess we have to call you an outlier :-)
anon
@Neil: You would not only have to make a measurement, but demonstrate some sort of causation/correlation to better code. I also edited my post with more arguments from my point of view.
DeadMG
@Neil: As i said, i don't think its representative :)
Georg Fritzsche
@DeadMG Doing a grep on your code would probably have expended less time than you composing this answer on why it is pointless, and might have yielded some useful data.
anon
@Neil: I don't have anywhere near enough code on me for it to be meaningful, even if doing such was useful. Besides, I've really got nothing better to do than debate the point right now.
DeadMG
@DeadMG SO is not a debating forum, so - goodbye.
anon
+2  A: 

In a project i co-own we have roughly 1307 throws vs. 88 trys due to somewhat uncommon requirements:

  • multiple entry points due to being a framework for dynamically loaded modules
  • propagating exceptions from a scripting enviroment as C++ exceptions
  • exception-oriented conversion-failure propagation
Georg Fritzsche