
In article <20060824085903.GF9119@google.com>, Gerhard Wesp <gwesp@google.com> wrote:
On Wed, Aug 23, 2006 at 11:20:20AM -0700, Emil Dotchevski wrote:
If I understand you correctly, you are storing a user message in the exception when you throw it, and then use std::exception::what() to retrieve it, right? This approach is problematic for several reasons, most notably
Indeed. I don't localize error messages, in fact I've never met a program that correctly and completely implemented localized error messages. I guess it's because the problem doesn't scale so well.
It doesn't really matter if a program correctly and completely implements localized error messages -- even if you only get the most common error messages translated into the most languages most commonly used among your users, you will make a huge difference in their ability to understand what your program is trying to tell them. Inability to solve the entire problem is not an excuse to try solving important parts of it. The problem of localizing error messages is not fundamentally harder than producing useful error messages in English. If you can do English well (and I do not consider "Parsing data file: couldn't open <filename>: <error>" to be a good error message in English), you probably have enough machinery in the code to do most other languages well, and localization becomes a simple matter of hiring translators. For example, the app that I work on will give you error messages such as "The file 'XYZZY' could not be transferred because you do not have the required permissions on the server." -- and that still leaves a lot of room for improvement. Importantly, though, once we built the ability to construct meaningful English sentences using information from high levels of the app (where the user action is know) and low levels of the app (where the precise failure is known), also doing so in the six other languages that we support was trivial.
because the user message has to be localized, but also because different programs may need to output different messages in response to the same exception thrown by a shared library.
Hmmm... Can you give an example? I try to restrict the what() string to be indepentent of library usage and add more information higher up the call stack, possibly re-throwing afterwards. E.g., a file object constructor might throw "couldn't open <filename>: <error>" and then, it's caller might prepend some more context information to make that either "Reading configuration file: couldn't open <filename>: <error>" or "Parsing data file: couldn't open <filename>: <error>"
This works quite well, but yeah, maybe there are situations where string concatenation is too simplistic.
Any time you attempt to address your users in a language that they use in everyday life, as opposed to the geek language that makes the programmers' lives easier, string concatenation is way too simplistic. Error information returned by a well-designed API carries enough semantic content for the clients of that API to use in their own representation of the errors -- different clients have different error reporting needs. As a result, there is nothing inherently wrong with using strings for identifying errors, as long as the exact values of those strings are documented as part of the API, and are maintained as any other part of the API (e.g., if you want to change one of them, you have to consider backward compatibility). Basically, if an API treats error strings returned as it would treat error codes returned, then there is no problem; on the other hand, if an API treats error strings as private values that clients cannot rely on, then the clients have their hands tied. (As an aside, part of what makes user-friendly error reporting difficult is the fact that many APIs have poorly defined error semantics in the first place.) Ben -- I changed my name: <http://periodic-kingdom.org/People/NameChange.php>