45.3. エラーメッセージのスタイルガイド

このスタイルガイドでは、PostgreSQLで生成される全てのメッセージに対する、一貫性維持、ユーザに親切なスタイルについての希望を説明します。

45.3.1. 何がどこで起こったか

主メッセージは、簡潔に事実を示すものにすべきです。 特定の関数名など実装の詳細への参照は止めるべきです。 "簡潔""ごく普通の条件下で1行に収まる"ことを意味します。 主メッセージを簡潔にするために必要であれば、また、特定のシステムコールが失敗したなど実装の詳細について記載したいのであれば、詳細メッセージを使用してください。 主メッセージ、詳細メッセージの両方は事実を示すものにすべきです。 どうすれば問題を解決できるかに関する提言には、その提言が常に適切とは限らない場合は特に、ヒントメッセージを使用してください。

例えば、

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

理論的根拠: 主メッセージを簡潔にすることは、要点を維持することを助けます。 そして、クライアントは、エラーメッセージ用に1行文確保すれば十分であるという仮定の下で画面設計を行うことができます。 詳細メッセージやヒントメッセージを冗長モードに格下げしたり、エラーの詳細を表示するウィンドウをポップアップさせることもできます。 また、詳細メッセージやヒントメッセージは通常ディスク容量を節約するためにサーバログには出力されません。 ユーザはどうやってもその詳細を知りませんので、実装の詳細への参照を避けることが最善です。

45.3.2. 整形

メッセージテキストの整形に関して、特定の前提を行わないでください。 クライアントやサーバログでは、自身の必要性に合わせて行を改行すると想定してください。 長めのメッセージでは、改行文字(\n)を推奨する段落の区切りを示すものとして使用しても構いません。 メッセージの終わりに改行を付けないでください。 タブや他の整形用文字を使用しないでください (エラーの内容の表示では、関数呼び出しなどのコンテキストのレベルを区切るために、改行が自動的に追加されます)。

理論的根拠: メッセージは必ずしも端末型のディスプレイに表示されるとは限りません。 GUIのディスプレイやブラウザでは、こうした書式指示はうまくいったとしても無視されます。

45.3.3. 引用符

英文では、引用が適切な場合には二重引用符を使用すべきです。 他の言語でのテキストは、出版上の慣習や他のプログラムのコンピュータ出力と矛盾しない種類の引用符の1つを一貫して使用してください。

理論的根拠: 二重引用符と単一引用符の選択はどちらかでもよいものですが、推奨する方がよく使われています。 SQL規約(すなわち文字列には単一引用符、識別子には二重引用符)に従って、オブジェクトの種類に応じて引用符を選択することを推奨する人もいます。 しかし、これは言語内部の技術的な事項であり、多くのユーザが理解できるものではありません。 また、他の種類の引用手法には拡張できません。 他の言語へ翻訳できません。 ですので、あまり意味がありません。

45.3.4. 引用符の使用

ファイル名、ユーザ提供の識別子、複数の単語を含む変数を区切るために引用符を使用してください。 複数の単語を含まない変数(例えば演算子名)には引用符を使用しないでください。

バックエンドには必要に応じて出力に二重引用符を付与する関数(例えばformat_type_be())があります。 こうした関数の出力の周りには引用符を追加しないでください。

理論的根拠: オブジェクトの名前をメッセージ内に埋め込む際に曖昧さが生じることがあります。 埋め込む名前がどこから始まりどこで終わるかついての表記には一貫性を持たせてください。 しかし、不必要にメッセージをまとめたり、引用符を二重にすることは止めてください。

45.3.5. 文法と句読点

この規則は、主エラーメッセージと詳細/ヒントメッセージとで異なります。

主エラーメッセージ: 最初の文字を大文字にしないでください。 メッセージの最後にピリオドを付けないでください。 メッセージの終わりに感嘆符を付けようとは考えないでください。

詳細メッセージとヒントメッセージ: 完全な文章を使用し、終わりにピリオドを付けてください。 文章の最初の単語は大文字にしてください。

理論的根拠: 句読点の禁止により、クライアントアプリケーションでは、そのメッセージを各種文法的なコンテキストに埋め込みやすくなります。 主メッセージはしばしば文法的に完全な文章になっていません (そして、1行以上の長さになりそうであれば、主メッセージと詳細メッセージに分割すべきです)。 しかし、詳細メッセージとヒントメッセージは、より長く、かつ複数の文章を持つ必要があるかもしれません。 一貫性のため、これらは、たとえ文章が1つだけであっても、完全な文章形式に従うべきです。

45.3.6. 大文字と小文字

メッセージの言葉使いでは小文字を使用してください。 主エラーメッセージの場合は先頭文字も含みます。 SQLコマンドとキーワードがメッセージ内に出現する場合は大文字を使用してください。

理論的根拠: メッセージは完全な文章かもしれませんし、そうではないかもしれませんので、この方法は、より簡単に全ての見た目の一貫性を向上します。

45.3.7. 受動態の禁止

能動態を使用してください。 能動的な主語がある("AはBを行うことができない")場合は完全な文章を使用してください。 主語がプログラム自体である場合は、主語を付けずに電報様式を使用してください。 プログラムに"I(私)"を使用しないでください。

理論的根拠: プログラムは人間ではありません。 他を真似ないでください。

45.3.8. 現在形と過去形

試行が失敗したが、次は(何らかの問題を修正した後に)成功するかもしれない場合は過去形を使用してください。 失敗が永続するようであれば、現在形を使用してください。

以下の2つの意味には無視できないほどの違いがあります。

could not open file "%s": %m

および

cannot open file "%s"

最初のものは、ファイルを開くことに失敗したことを意味します。 メッセージには、"ディスクが一杯""ファイルが存在しない"といった、その理由を付けるべきです。 次回はディスクに空きがあるかもしれませんし、問題のファイルが存在するかもしれませんので過去形が適切です。

2番目の形式は、そのプログラム内の指名されたファイルを開く機能が存在しない、あるいは、概念的に不可能であることを示します。 この条件は永遠に続きますので現在形が適切です。

理論的根拠: 仮定ですが、一般的なユーザは単なるメッセージの時制から多くを意味を引き出すことはできないでしょう。 しかし、言語が文法を提供してくれますので、それを正確に使用すべきでしょう。

45.3.9. オブジェクトの種類

オブジェクトの名前を引用する時、そのオブジェクトの種類を記載してください。

理論的根拠: さもないと、"foo.bar.baz"が何なのか誰もわかりません。

45.3.10. 角括弧

角括弧は、(1)コマンドの概要にて省略可能な引数を表す、(2)配列の添字を表す、ためだけに使用されます。

理論的根拠: 広く知られる慣習に対応するものがなく、人々を混乱させることになります。

45.3.11. エラーメッセージの組み立て

メッセージに、他で生成されるテキストを含める場合、以下の様式で埋め込んでください。

could not open file %s: %m

理論的根拠: 全ての起こり得るエラーコードを単一のなめらかな文章に埋め込むことを考えることは困難です。 ですので、何らかの句読点が必要とされます。 括弧の中にテキストを埋め込むこともまた推奨されていましたが、よくある埋め込むテキストがそのメッセージの最も重要となる場合は不自然です。

45.3.12. エラーの理由

メッセージは常にエラーが発生した理由を記述すべきです。 以下に例を示します。

BAD:    could not open file %s
BETTER: could not open file %s (I/O failure)

理由がわからない場合は、コードを直すべきです。

45.3.13. 関数名

エラーテキストには、それを報告したルーチンの名前を含めないでください。 必要に応じて、そのルーチンを見つける他の機構があり、また、ほとんどのユーザにとって役に立つ情報ではありません。 関数名がないと、エラーメッセージにあまり意味がないのであれば、言葉使いを変えてください。

BAD:    pg_atoi: error in "z": can't parse "z"
BETTER: invalid input syntax for integer: "z"

同時に呼び出した関数名の記述も止めてください。 代わりにそのコードが何をしようとしたのかを記述してください。

BAD:    open() failed: %m
BETTER: could not open file %s: %m

もし本当に必要であれば、詳細メッセージにそのシステムコールを記載してください (詳細メッセージの情報としてシステムコールに実際に渡した値を与えることが適切な場合もあります)。

理論的根拠: ユーザはその関数が何を行うのかを知りません。

45.3.14. ややこしい単語の防止

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"を使用すると、弱く取られ、問題が混乱します。

45.3.15. 適切なスペル

単語の完全なスペルを使用してください。 例えば、以下は止めてください。

理論的根拠: これは一貫性を向上します。

45.3.16. 地域化

エラーメッセージは他の言語に翻訳される必要があることを忘れないでください。 項46.2.2のガイドラインに従い、翻訳者に苦労を強いることを防いでください。