On Monday, February 20, 2012 11:57:07 Andrei Alexandrescu wrote: > On 2/20/12 11:44 AM, foobar wrote: > > This extra processing is orthogonal to the exception. the same exception > > can be logged to a file, processed (per above example) and generate > > graphical notification to the user, etc. The exception contains the > > information pertaining only to what went wrong. the rest is not part of > > this discussion. > > Exactly. I don't see how a disagreement follows from here. So isn't it > reasonable to design the exception such that it can offer information > pertaining to what went wrong, in a uniform manner?
In most cases, that's not even vaguely possible. An exception for a socket would probably include an IP and port in its additonal information. An exception for a file operation would include the file name that it tried to operate on. An exception for malformed unicode would include information on the string and the bad character. An exception from parsing XML would give you information about which part of the XML had the problem and what the problem was. All of these situations are completely different. Using a Variant is the equivalent of using a void* and casting to the actual information based no the type of the exception or on a type code in the exception. How is that better than simply having an actual exception hierarchy with each of the derived exceptions having fields specific to their circumstances? I contend that it's far worse. It's throwing away type information simply in an effort to genericize. Genericity can be very useful, but it can also be over-applied. I don't see how you could possibly make that uniform. It's very non-uniform by its very nature. The handling _needs_ to be non-uniform. > > The exact same exception in the example would also be thrown on a > > mistyped URL in an application that tries to scrape some info from a > > website for further processing. The error is still the same - the url is > > incorrect but different use cases handle it differently. In the former > > example I might call to a i18n lib (someone already mentioned gettext) > > while in the latter I'll call a logging library with the the mistyped > > url (for statistics' sake). > > in the first I use the url to find a closest match, in the second I want > > to log said requested url. Both handled by *other* mechanisms. > > in both cases the exception needs a url field and in both cases I have > > no need for the Variant[string] map. > > The Variant[string] map saves a lot of duplication whenever you want to > format a human-readable string (which is a common activity with > exceptions). It transforms this (I'm too lazy to write code anew by > hand, so I'll paste Jonathan's): > [snip] > > The stringTemplate function loads the formatting template from a table > indexed on typeid(e).toString() and formats it with the info. It's > simple factorization. That only works in this particular case, because it happens that the code is just figuring out how to translate the exception into an error message without trying to recover. If you want to do anything fancier (like suggest the flag that the user probably meant), you need those extra fields in the exceptions. Also, much of the time, the application is going to want to print its own error messages, not what library that its calling used. And frequently, the application can give much better messages, because it knows what it's doing, not just the operation that it tried and failed. Exceptions are for _developers_, not users, and in general, exception messages should not be printed to users. And moving any messages that exceptions have out of the exception itself is _bad_ for debugging. The exception should contain its own information, not have it externalized for internationalization purposes. If its in the exception itself, you can see it in the debugger. That doesn't work anywhere near as well when you externalize its stuff. I gave the getopt example, because we were talking about getopt, and it was easy to write. It shows one way that the fields in the exception could be useful. But it's an abnormality in that it's whole purpose is to allow you to figure out how to best give an error message to the user. Many, many other exceptions need to be processed by the program without necessarily informing the user of anything. So, getopt was probably a bad example. It just was an easy one to give. - Jonathan M Davis
