提供此样式指南是为了希望在 PostgreSQL 生成的所有消息中都保持一致、对用户友好的样式。
主要消息应简洁、客观,并避免提及具体函数名称等实现细节。“简洁” 的意思是 “正常情况下应该能放在一行内”。如有需要,使用详细信息消息以保持主要消息简洁,或如果您觉得需要提及实现细节,例如失败的特定系统调用。主要消息和详细信息消息都应客观。对解决问题的建议使用提示消息,特别是如果您觉得这个建议可能并不总是适用。
例如,不应使用
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, written as a complete sentence.
推理:保持主要消息简洁有助于重点突出,还能让客户端假设有一行用来显示错误信息,继而对屏幕空间进行布局。详细信息和提示消息可以降级到冗余模式,或者弹出一个错误详情窗口。另外,通常会从服务器日志中删除详情和提示以节省空间。最好避免提及实现细节,因为用户不应该知道这些细节。
请不要将任何特定格式假设都放入消息文本中。让客户端和服务器日志根据自己的需要来换行。在长消息中,换行符 (\n) 可以用来表示建议的分段。请不要以换行符结尾。请勿使用制表符或其他格式字符。(在错误内容显示中,会自动添加换行符以分隔上下文的不同级别,例如函数调用。)
推理:消息并不一定会显示在终端型显示器上。在 GUI 显示或浏览器中,这些格式化说明充其量只是被忽略。
如需引用,英文文本应使用双引号。其他语言的文本应始终使用与其他程序的出版惯例及计算机输出相符的一种引号。
推理:选择双引号而不是单引号在一定程度上是任意的,但倾向于优先使用双引号。一些人建议根据 SQL 惯例选择引号类型,具体情况取决于对象的类型(即用单引号表示字符串,用双引号表示标识符)。但这只是一个语言内部的技术问题,许多用户甚至都不熟悉,对于其他类型的带引号的术语没有可扩展性,翻译到其他语言也不行,而且一点意义也没有。
务必使用引号来分隔文件名、用户提供的标识符、配置变量名称以及其他可能包含单词的变量。不要用引号标记不会包含单词的变量(例如,运算符名称)。
后端有函数会根据需要对其自己的输出加上双引号(例如,format_type_be()
)。请不要在这些函数的输出周围添加其他引号。
基本原理:当嵌入在消息中时,对象的名称可能会造成歧义。对于插入名称开始和结束的位置,采用一致的表示方式。但是,不要使用不必要的或重复的引号来弄乱消息。
主错误消息和详细说明/提示消息的规则不同
主错误消息:不要将首字母大写。不要以句号结束消息。甚至不要考虑以感叹号结束消息。
详细说明和提示消息:使用完整句子,每个句子以句号结尾。将句子的第一个单词大写。如果后跟另一个句子,则在句号后加两个空格(适用于英文文本;在其他语言中可能不合适)。
错误上下文字符串:不要将首字母大写,也不要以句号结束字符串。上下文字符串通常不应该是完整句子。
基本原理:避免使用标点符号,让客户端应用程序更轻松地将消息嵌入到各种语法上下文中。通常,主消息根本不是语法完整的句子。(并且,如果它们足够长以构成一个以上的句子,则应将它们拆分为主部分和详细说明部分。)但是,详细说明和提示消息较长,并且可能需要包含多个句子。为了保持一致,即使只有一个句子也应将其编为完整句子样式。
将小写字母用于消息表述,包括主错误消息的首字母。如果消息中出现 SQL 命令和关键字,请对其使用大写。
基本原理:这样做会更容易让所有内容看起来更一致,因为有些消息是完整句子,而有些不是。
使用主动语态。在有动作主语时,使用完整句子(“A 无法执行 B”)。如果主语是程序本身,则使用无主语的电报式;不要对程序使用 “我”。
基本原理:该程序不是人。不要假装它不是人。
如果尝试做某事失败,但可能在下一次成功(可能是解决了一些问题后),请使用过去时。如果失败肯定是永久性的,则使用现在时。
如下形式的句子之间存在非平凡的语义差异
could not open file "%s": %m
和
cannot open file "%s"
第一个意味着打开文件尝试失败。消息应给出原因,如“磁盘已满”或“文件不存在”。使用过去时态的原因是,下一次磁盘可能不再满了,或存在所讨论的文件。
第二种形式表示在程序中根本不存在打开所命名文件名功能,或在概念上无法实现。使用现在时态的原因是,此条件将无限期存在。
基本原理:诚然,普通用户不可能仅从消息时态中得出很重要的结论,但既然语言为我们提供语法,我们就应正确使用它。
当消息包含在其他地方生成文本时,将其嵌入如下样式
could not open file %s: %m
基本原理:难以针对所有可能的错误代码进行记述以将其粘贴成一个简单的句子,因此需要某种标点符号。有人也建议将嵌入文本放入括号中,但如果嵌入文本可能是消息的最重要组成部分(这种情况很常见),这样就不自然。
消息应始终说明发生错误的原因。例如
BAD: could not open file %s BETTER: could not open file %s (I/O failure)
如果您不知道原因,最好修复此代码。
请勿在错误文本中包含报告例程名称。我们有其他机制可在需要时找出原因,对于大多数用户来说,这并非有用信息。如果错误文本在没有函数名称的情况下变得不太有意义,请重新表述它。
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
如果确实有必要,请在详细消息中提及系统调用。(在某些情况下,向系统调用提供实际传递值可能会成为详细消息的适当信息。)
基本原理:用户不知道所有这些函数的作用。
无法。 “无法”近似于被动语态。根据情况,最好使用“不能”或“无法”。
错误。错误消息,例如 “结果错误” 很容易理解。最好写明结果为什么 “错误”,例如,“无效格式”。
非法。 “非法” 触犯法律,其余是 “无效”。最好说清楚为什么无效。
未知。尽量避免 “未知”。可考虑 “错误:未知响应”。如果您不知道响应是什么,您怎么知道是有错误的?“无法识别” 往往是更好的选择。此外,一定要注明投诉的值。
BAD: unknown node type BETTER: unrecognized node type: 42
查找与存在。如果程序使用非平凡算法来查找资源(例如,路径搜索),并且该算法失败,那么可以公正地说程序无法 “查找” 资源。另一方面,如果知道资源的预期位置,但程序无法在那里访问它,那么可以说该资源 “不存在”。在这种情况下使用 “查找” 听起来很无力,而且会混淆问题。
可能与能否与可能会。 “可能” 建议允许(例如,“您可以借用我的耙子。”),在文档或错误消息中很少使用。 “能够” 表明有能力(例如,“我可以抬动那根原木。”),“可能会” 表明可能性(例如,“今天可能会下雨。”)。使用适当的词语可以澄清含义并辅助翻译。
缩写。避免使用缩写,比如 “不能”;改为使用 “不可以”。
非负。避免使用 “非负”,因为它对是否接受零值不明确。最好使用 “大于零” 或 “大于或等于零”。
请记住,错误消息文本需要翻译成其他语言。请遵循 第 55.2.2 节 中的指导原则,以避免给翻译人员带来困难。