提供此樣式指南,希望能維護 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) 可用於指示建議的段落分隔。不要以換行符號結束訊息。不要使用 Tab 或其他格式化字元。(在錯誤上下文中顯示,會自動新增換行符號以分隔各層級的上下文,例如函式呼叫。)
理由:訊息不一定會顯示在終端機類型的顯示器上。在 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
如果確實有必要,請在詳細訊息中提及系統呼叫。(在某些情況下,提供傳遞給系統呼叫的實際值可能適合作為詳細訊息的資訊。)
理由:使用者不知道所有這些函數的作用。
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” 資源。 另一方面,如果已知資源的預期位置,但程式無法在那裡存取它,則說資源不 “exist”。 在這種情況下使用 “find” 聽起來很弱並且混淆了問題。
May(可能) vs. Can(可以) vs. Might(或許). “May” 表示許可(例如,“You may borrow my rake.” [你可以借我的耙子]),在文件或錯誤訊息中很少使用。 “Can” 表示能力(例如,“I can lift that log.” [我可以抬起那根圓木]),而 “might” 表示可能性(例如,“It might rain today.” [今天可能會下雨])。 使用正確的詞可以闡明意義並有助於翻譯。
縮寫. 避免縮寫,例如 “can't”;改用 “cannot”。
Non-negative(非負數). 避免使用 “non-negative”,因為它對於是否接受零存在歧義。 最好使用 “greater than zero(大於零)” 或 “greater than or equal to zero(大於或等於零)”。
請記住,錯誤訊息文字需要翻譯成其他語言。 遵循第 55.2.2 節中的指南,以避免使翻譯人員的生活變得困難。
如果您在文件中發現任何不正確、與您對特定功能的體驗不符或需要進一步澄清的內容,請使用此表單來報告文件問題。