Active debugging. You're actually running a debugger while writing code and trying to figure out what happens. In this context, a helpful exception will guide you by making it easy to understand what's going wrong, or eventually suggesting a workaround (although this is optional).
Passive debugging. The code runs in production and fails. The exception is logged, but you only get the message and the stack trace. In this context, a helpful exception message will help you quickly localize the bug.
Since those messages are often logged, it'sit also means that you shouldn't include sensitive information there (such as private keys or passwords, even if it could be useful to debug the app).
This also means that if you cannot provide any additional information which is not already in the type of the exception, you can keep the message empty. DivisionByZeroException
is a good example where the message is redundant. On the other hand, the fact that most languages let you throw an exception without specifying its message is done for a different reason: either because the default message is already available, or because it will be generated later if needed (and the generation of this message is enclosed within the exception type, which makes perfect sense, OOPly"OOPly" speaking).
Handles exceptions in the first place. Most ones can be handled without disturbing the user. Network is down? Why not waitingwait for a few seconds and try again?
Prevents a user from leading the application to an exceptional case. If you ask the user to enter two numbers and divide the first one by the second one, why would you let the user to enter zero in the second case in order to blame him a few seconds later? What about highlighting the text box in red (with a helpful tool tip telling that the number should be different than zero) and disabling the validation button until the field remains red?
Invites a user to perform an action in a form which is not an error. There are no enough permissions to access a file? Why not askingask the user to grant administrative permissions, or pick a different file?
If nothing else works, shows a helpful, friendly error which is specifically written to reduce user's frustration, help the user to understand what went wrong and eventually solve the problem, and also help him prevent the error in the future (when applicable).
In your question, you suggested to have two messages in an exception: a technical one for developers, and the one for end users. While this is a valid suggestion in some minor cases, most exceptions are produced at a level where it is impossible to produce a meaningful message for the users. Take
DivisionByZeroException
and imagine that we couldn't prevent the exception from happening and can't handle it ourselves. When the division occurs, does the framework (since it's the framework, and not business code, which throws the exception) know what will be a helpful message for a user? Absolutely not:The division by zero occurred. [OK]
Instead, one can let it throw the exception, and then catch it at a higher level where we knew the business context and could act accordingly in order to actually help the end user, thus showing something like:
The field D13 cannot have the value identical to the one in field E6, because the subtraction of those values is used as a divisor. [OK]
or maybe:
The values reported by ATP service are inconsistent with the local data. This may be caused by the local data being out of sync. Would you like to synchronize the shipping information and retry? [Yes] [No]