你应该报告异常消息的文本吗?

12
考虑一些可能会抛出已检查异常(类型为Exception的异常)的代码。当然,您的代码会捕获该异常。您不仅仅是吞噬了该异常,而且您的代码还通过用户界面以某种方式向用户报告了该异常。也许是在日志文件中,或者使用GUI弹出窗口。
您向用户报告的文本是否应包括异常的消息文本?也就是说,Throwable.getMessage()Throwable.getLocalizedMessage()提供的文本?
我认为不应该,但似乎很多人不同意我的看法。那么我错在哪里了呢?我的论点如下。
  • 当异常被抛出时,消息是在异常创建时生成的。因此,它最多只能提供非常低级别的信息,可能不适合向用户报告。
  • 从哲学上讲,使用消息似乎违背了异常的整个目的,即将错误处理(throw部分)的检测和启动与处理和报告的完成(catch部分)分离。使用消息意味着消息必须适合报告,这将责任转移给应该负责仅检测和启动的位置。也就是说,我认为Throwable设计中的getMessage()部分是一个错误。
  • 消息没有本地化。尽管它的名称是getLocalizedMessage(),但并不是很有用,因为在捕获异常之前可能不知道要使用哪种语言环境(是要将报告发送到由英语系统管理员读取的系统日志,还是要弹出窗口供GUI的法国用户使用?)。
  • 我听说Java 7具有更改进的IOException异常层次结构,使您能够在不同的catch子句中处理不同类型的I/O错误,从而使getMessage()文本变得不那么重要。这意味着即使Java设计师对getMessage()也有些不舒服。

我不是在询问报告堆栈跟踪是否有用。堆栈跟踪只对暗示错误的异常有用。也就是说,对于未经检查的异常。我认为在这种情况下,提供异常消息的低级详细信息不仅有用而且是强制性的。但我的问题涉及到已检查的异常,例如文件未找到。
我也不是在询问消息文本的最佳实践

一个相关的问题:https://dev59.com/Zk3Sa4cB1Zd3GeqPw6i8 - Raedwald
没有一种适合所有人的解决方案。它取决于“你的目标受众是谁?” - Pacerier
是我自己的问题还是被选中的答案完全没有回答问题的重点? - Brent Bradburn
可能是自定义异常消息:最佳实践的重复问题。 - 8protons
4个回答

9
如果您向用户呈现错误条件,应该是用户友好的信息。异常包含技术细节,用户不需要知道/也不应该知道。
在某些情况下,呈现堆栈跟踪信息可能会涉及安全问题,因此永远不应向用户显示堆栈跟踪。
如果您向用户显示错误消息,则在某个时刻您需要有意识地决定显示弹出窗口或将消息添加到日志窗口中。在那个时刻,您可以将任何异常转换为更适合用户的消息。请注意,您可能需要比默认的“异常”类型提供更多的信息,因此您可以/应该创建自己的Exception类型,其中包含所有您需要向用户呈现所需数据的信息。

1
堆栈跟踪只对建议存在错误的异常有用。也就是说,对于未经检查的异常。我认为在这种情况下,提供异常消息的低级细节不仅有用,而且是必需的。但我的问题涉及到检查异常,比如文件未找到。 - Raedwald
如果由于严重的错误而引发异常,您希望QA检测到它。尽管如此,如果应用程序崩溃,您可以显示一条消息,要求用户提交报告以进行复制。如果您没有任何隐藏详细信息的安全要求,则显示堆栈跟踪。 - hvgotcodes

8
不应该直接在错误消息中向用户显示异常,因为这些是低级技术细节,用户几乎总是希望得到更易于理解的信息,即使它提供的信息不如堆栈跟踪详尽!
我说“几乎总是”,因为有些情况下(如在IDE中),您可以认为用户具备足够的技术能力来查看堆栈跟踪;事实上,在这种情况下,他们可能会更喜欢“简化”的错误消息。
然而,个人认为应始终将堆栈跟踪记录在用户可以访问的某个位置,以便如果他们抱怨“程序不工作”,则可以在他们发送文件时查看确切发生了什么。

5
在一些项目中,我会创建一种特殊的异常(比如UserFriendlyException)。这种异常类型必须拥有用户友好的错误信息。如果我捕获到这样的异常,我可以将其展示给用户。
这使得使用异常来处理用户友好的错误成为可能,并防止向用户显示非常技术化的信息。

2
这仍然将创建用户友好消息的责任放在throw异常的位置,而不是catch异常的位置。它仅仅用getFriendlyMessage()替换了getMessage(),似乎并没有太多收获。 - Raedwald

1
我认为您不应该向用户显示异常消息本身,它只应该出现在日志中。即使您已经特意使其用户友好,也不应该显示,因为这些消息很难国际化。您应该想出一些机制,使您的UI层能够理解并将其解析为代码,以便您可以查找可国际化的消息来显示给用户。我发现带有“代码”属性/枚举的异常非常有效。非常具体的异常也可以,但维护起来可能会很混乱。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接