4

从理论上讲,最终用户永远不会看到内部错误。但在实践中,理论和实践是不同的。所以问题是向最终用户展示什么。现在,对于完全非技术的用户,您希望尽可能少地显示(“单击此处提交错误报告”之类的东西),但对于更高级的用户,他们会想知道是否有解决方法,如果它已经知道了一段时间,等等。所以你想包括一些关于什么是错误的信息。

执行此操作的经典方法是使用文件名:行号的断言或具有相同的堆栈跟踪。现在这对开发人员来说是件好事,因为它把问题指向了他;但是它对用户来说有一些明显的缺点,特别是它非常神秘(例如不友好)并且代码更改会更改错误消息(谷歌搜索错误仅适用于此版本)。

我有一个程序,我正计划在我想解决这些问题的地方编写程序。我想要的是一种将唯一身份附加到每个断言的方法,这样编辑断言周围的代码不会改变它。(例如,如果我将它剪切/粘贴到另一个文件,我希望显示相同的信息)有什么想法吗?

我正在考虑的一种方法是对错误进行枚举,但是如何确保它们永远不会在多个地方使用呢?

(注意:对于这个问题,只关注由编码错误引起的错误。而不是像错误输入这样可能合法发生的事情。OTOH 这些错误可能会引起整个社区的兴趣。)

(注 2:有问题的程序将是在用户系统上运行的命令行应用程序。但同样,这只是我的情况。)

(注 3:目标语言是D我非常愿意深入研究元编程。非常欢迎其他语言的答案!)

(注 4:我明确不想使用实际的代码位置,而是使用某种符号名称来表示错误。这是因为如果代码以任何方式更改,代码位置也会发生变化。)

4

3 回答 3

2

有趣的问题。我多次使用的解决方案是:如果是致命错误(例如,非致命错误应该让用户有机会更正输入),我们生成一个包含大量相关信息的文件:请求变量,标头、内部配置信息和完整的回溯,以供以后调试。我们将其存储在具有生成的唯一文件名的文件中(并以时间为前缀)。

对于用户,我们会显示一个页面,说明发生了不可恢复的错误,并要求他们在报告错误时包含文件名作为参考。使用来自违规请求的上下文的所有这些信息进行调试要容易得多。

在 PHP 中,debug_backtrace() 函数对此非常有用。我敢肯定你的平台有一个等价物。

还要记得发送相关的 http 标头:可能:HTTP/1.1 500 Internal Server Error

给定错误报告文件的合理格式,还可以分析用户未报告的错误。

于 2008-11-25T19:53:30.067 回答
1

编写一个脚本来 grep 你的整个源代码树以使用这些错误代码,然后如果有重复则抱怨。将该脚本作为单元测试的一部分运行。

于 2008-11-25T19:54:44.213 回答
1

我对您的目标语言一无所知,但这是一个有趣的问题,我已经考虑过,我想加两分钱。

我的感觉一直是硬错误和内部错误的消息应该尽可能有用,以便开发人员识别问题并快速修复它。大多数用户甚至不会查看此错误消息,但高度复杂的最终用户(可能是技术支持人员)通常会很好地了解问题所在,甚至通过查看非常详细的错误消息来提出新颖的解决方法。关键是让这些错误消息详细而不神秘,这更像是一门艺术而不是一门科学。

来自使用进程外 COM 服务器的 Windows 程序的示例。如果主程序尝试从 COM 服务器实例化对象并失败并显示错误消息:

“警告:无法实例化 UtilityObject:‘CoCreateInstance’中的错误‘类未注册’”

99% 的用户会看到这个并认为它是用希腊语写的。技术支持人员可能很快意识到他们需要重新注册 COM 服务器。开发人员将确切地知道出了什么问题。

为了将一些上下文信息与断言相关联,在我的 C++ 代码中,我经常使用带有方法名称的简单字符串,或者其他可以明确错误发生位置的字符串(我很抱歉以您没有使用的语言回答不要问):

int someFunction()
{
  static const std::string loc = "someFunction";
  :  :
  if( somethingWentWrong )
  {
    WarningMessage(loc.c_str(), "Unable to Instantiate UtilityObject:  Error 'Class Not
    Registered' in 'CoCreateInstance);
  }
}

...生成:

警告 [someFunction]:无法实例化 UtilityObject:“CoCreateInstance”中的“类未注册”错误

于 2008-11-26T05:32:12.237 回答