Postgresql 中文操作指南
56.3. Error Message Style Guide #
提供此风格指南,旨在使 PostgreSQL 生成的所有消息始终保持一致、对用户友好。
What Goes Where #
主要消息应简短、真实,并避免提及实现细节,例如特定函数名称。“简短”意味着“在正常情况下应放在一行上”。在需要时使用详细消息来保持主要消息简短,或者如果你觉得需要提及实现细节,例如失败的特定系统调用。主要消息和详细消息都必须真实。对于如何解决问题提出建议,请使用提示消息,尤其是此建议可能并不总是适用的情况下。
例如,不要以下面的方式编写:
IpcMemoryCreate: shmget(key=%d, size=%u, 0%o) failed: %m
(plus a long addendum that is basically a hint)
应如下编写:
Primary: could not create shared memory segment: %m
Detail: Failed syscall was shmget(key=%d, size=%u, 0%o).
Hint: the addendum
基本原理:保持主要消息简短有助于切中要点,并让客户端在假定一行足以容纳错误消息的情况下布局屏幕空间。可以将详细消息和提示消息降级为冗余模式,或者可能是弹出错误详细信息窗口。此外,通常会从服务器日志中取消显示详细信息和提示,以节省空间。最好避免提及实现细节,因为用户不需要了解这些细节。
Formatting #
不要在消息文本中放入任何有关格式化的特定假设。预计客户端和服务器日志将换行以满足它们自己的需要。在长消息中,换行符 (\n) 可用于指示建议的段落断行。不要以换行符结束消息。不要使用制表符或其他格式化字符。(在错误上下文中显示时,将自动换行来区分上下文的层次,例如函数调用。)
基本原理:消息不一定显示在终端类型显示设备上。在 GUI 显示设备或浏览器中,这些格式化说明充其量会被忽略。
Quotation Marks #
当引用适合时,英文文本应使用双引号。其他语言中的文本应始终使用一种引用,该引用与出版习惯和计算机中其他程序的文本输出一致。
基本原理:选择双引号而非单引号在一定程度上是任意的,但往往更偏好使用双引号。有人建议根据 SQL 约定(即,单引号引用的字符串、双引号引用的标识符)选择引号类型,具体取决于对象类型。但这是一种语言内部技术问题,许多用户甚至不了解,它不能扩展到其他类型的带引号术语,也不能转换为其他语言,而且也没有什么意义。
Use of Quotes #
始终使用引号来分隔文件名、用户提供的标识符和其他可能包含单词的变量。不要使用它们来标记不会包含单词的变量(例如,运算符名称)。
后端有函数会根据需要对其自己的输出加上双引号(例如 format_type_be())。不要在这些函数的输出周围加上其他引号。
基本原理:对象可以具有在嵌入到消息中时会产生歧义的名称。始终一致地表示插入名称的开始和结束位置。但不要用不必要或重复的引号使消息变得杂乱。
Grammar and Punctuation #
主要错误消息和详细/提示消息的规则不同:
主要错误消息:不要大写第一个字母。不要以句号结束消息。甚至不要考虑以感叹号结束消息。
详细消息和提示消息:使用完整的句子,并以句号结束每个句子。大写句子的第一个单词。如果后面还有另一个句子,则在句号后加两个空格(对于英文;在其他语言中可能不合适)。
错误上下文字符串:不要对第一个字母大写,也不要以句号结束字符串。上下文字符串通常不应是完整句子。
基本原理:避免标点符号可以让客户端应用程序更容易将消息嵌入到各种语法环境中。通常,主要消息本身并不是语法完整的句子。(并且如果它们足够长以超过一个句子,则应将它们拆分为主要部分和详细部分。)但是,详情和提示消息更长,可能需要包括多个句子。为了保持一致性,即使只有一句话,也应遵循完整的句子样式。
Upper Case vs. Lower Case #
对于消息措辞使用小写,包括主要错误消息的第一个字母。如果消息中出现 SQL 命令和关键字,则使用大写。
基本原理:这样可以更容易地使所有内容看起来更加一致,因为有些消息是完整的句子,而有些不是。
Avoid Passive Voice #
使用主动语态。如果有作用主语,则使用完整句子(“A 无法执行 B”)。如果主语是程序本身,则使用不带主语的电报样式;不要为程序使用“I”。
基本原理:该程序不是人类。不要假装它不是。
Present vs. Past Tense #
如果尝试做某事失败,但可能在下次成功(也许在修复某些问题后),则使用过去时。如果失败是肯定永久性的,则使用现在时。
以下形式的句子之间有非平凡的语义差异:
could not open file "%s": %m
及:
cannot open file "%s"
第一个句子表示打开文件失败。消息应给出原因,例如“磁盘已满”或“文件不存在”。过去时是合适的,因为下次磁盘可能不再满了或可能存在该文件。
第二种形式表示在程序中根本不存在打开指定文件的功能,或者在概念上这是不可能的。现在时是合适的,因为该条件会无限期地持续下去。
基本原理:确实,普通用户将无法仅从消息的时态中得出确定的结论,但既然语言向我们提供了语法,我们就应该正确使用它。
Assembling Error Messages #
当消息包含在其他地方生成文本时,请使用以下样式嵌入它:
could not open file %s: %m
基本原理:很难考虑所有可能的错误代码才能将此粘贴到一个平滑的句子中,因此需要某种标点符号。也有人建议将嵌入文本放在括号中,但如果嵌入文本很可能是消息中最重要的一部分,就像通常的情况一样,那就显得不自然。
Reasons for Errors #
消息应始终说明错误发生的原因。例如:
BAD: could not open file %s
BETTER: could not open file %s (I/O failure)
如果没有已知原因,则您最好修复该代码。
Function Names #
在错误文本中不要包含报告例程的名称。我们有其他机制可以在需要时找出该名称,对于大多数用户来说,这不是有用的信息。如果在没有函数名称的情况下错误文本没有多大意义,请重新表述。
BAD: pg_strtoint32: error in "z": cannot parse "z"
BETTER: invalid input syntax for type integer: "z"
同样,避免提及已调用的函数名称;相反,说明代码试图做什么:
BAD: open() failed: %m
BETTER: could not open file %s: %m
如果真的有必要,请在详细信息中提及系统调用。(在某些情况下,向详细信息中提供传递给系统调用的实际值可能是适当的信息。)
理由:用户不知道所有这些函数的作用。
Tricky Words to Avoid #
*Unable. * “Unable” 近似于被动语态。在适当的情况下,更好使用 “cannot” 或 “could not”。
*Bad. * 像“bad result”这样的错误消息很难从语法上进行合理解释。最好写出为何结果“bad”,例如“invalid format”。
*Illegal. * “Illegal”代表违法,其他情况则是“invalid”。更好的做法是,说明为何无效。
*Unknown. * 尽量避免使用“unknown”。考虑“error: unknown response”。如果您不知道响应是什么,您怎么知道响应是错误的?“Unrecognized”通常是更好的选择。此外,务必包括引起抱怨的值。
BAD: unknown node type
BETTER: unrecognized node type: 42
*Find vs. Exists. * 如果程序使用非平凡的算法来查找资源(例如,路径搜索)并且该算法失败,则可以说程序无法“找到”该资源。另一方面,如果资源的预期位置已知,但程序无法在那里访问该资源,则可以说该资源“不存在”。在这种情况下,使用“find”听起来很无力,并且会导致混淆。
*May vs. Can vs. Might. * “May”表示许可(例如,“You may borrow my rake.”),在文档或错误消息中很少使用。“Can”表示能力(例如,“I can lift that log.”),而“might”表示可能性(例如,“It might rain today.”)。使用正确的单词可以阐明含义并协助翻译。
*Contractions. * 避免使用缩写,例如“can’t”;而应改为使用“cannot”。
*Non-negative. * 避免使用“non-negative”,因为对于它是否接受零,它不够明确。最好使用“greater than zero”或“greater than or equal to zero”。
Localization #
请记住,错误消息文本需要翻译成其他语言。按照 Section 57.2.2中的指南进行操作,以免给翻译人员带来困难。