From 8ac5cd7d7870cb75c04bc366669d4d60f4d44821 Mon Sep 17 00:00:00 2001 From: Alexander Kuzmenkov <36882414+akuzm@users.noreply.github.com> Date: Mon, 1 Jun 2020 15:39:03 +0300 Subject: [PATCH] Add a guide on error messages. --- docs/ru/development/style.md | 69 ++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/docs/ru/development/style.md b/docs/ru/development/style.md index b7fff2753d..7238ebbcb2 100644 --- a/docs/ru/development/style.md +++ b/docs/ru/development/style.md @@ -692,6 +692,75 @@ auto s = std::string{"Hello"}; **2.** Спецификаторы исключений из C++03 не используются. +## Сообщения об ошибках {#error-messages} + +Сообщения об ошибках -- это часть пользовательского интерфейса программы, предназначенная для того, чтобы позволить пользователю: +* замечать ошибочные ситуации, +* понимать их смысл и причины, +* устранять эти ситуации. + +Форма и содержание сообщений об ошибках должны способствовать достижению этих целей. + +Есть два основных вида ошибок: +* пользовательская или системная ошибка, +* внутренняя программная ошибка. + +### Пользовательская ошибка {#error-messages-user-error} + +Такая ошибка вызвана действиями пользователя (неверный синтаксис запроса) или конфигурацией внешних систем (кончилось место на диске). Предполагается, что пользователь может устранить её самостоятельно. Для этого в сообщении об ошибке должна содержаться следующая информация: +* что произошло. Это должно объясняться в пользовательских терминах (`Function pow() is not supported for data type UInt128`), а не загадочными конструкциями из кода (`runtime overload resolution failed in DB::BinaryOperationBuilder::Impl, UInt128, Int8>::kaboongleFastPath()`). +* почему/где/когда -- любой контекст, который помогает отладить проблему. Представьте, как бы её отлаживали вы (программировать и пользоваться отладчиком нельзя). +* что можно предпринять для устранения ошибки. Здесь можно перечислить типичные причины проблемы, настройки, влияющие на это поведение, и так далее. + +Пример нормального сообщения: +``` +No alias for subquery or table function in JOIN (set joined_subquery_requires_alias=0 to disable restriction). +While processing '(SELECT 2 AS a)'. +``` +Сказано что не хватает алиаса, показано, для какой части запроса, и предложена настройка, позволяющая ослабить это требование. + +Пример катастрофически плохого сообщения: +``` +The dictionary is configured incorrectly. +``` +Из него не понятно: +- какой словарь? +- в чём ошибка конфигурации? + +Что может сделать пользователь в такой ситуации: применять внешние отладочные инструменты, спрашивать совета на форумах, гадать на кофейной гуще, и, конечно же, ненавидеть софт, который над ним так издевается. Не нужно издеваться над пользователями, это плохой UX. + + +### Внутренняя программная ошибка {#error-messages-internal-error} + +Такая ошибка вызвана нарушением внутренних инвариантов программы: например, внутренняя функция вызвана с неверными параметрами, не совпадают размеры колонок в блоке, произошло разыменование нулевого указателя, и так далее. Сигналы типа `SIGSEGV` относятся к этой же категории. + +Появление такой ошибки всегда свидетельствует о наличии бага в программе. Пользователь не может исправить такую ошибку самостоятельно, и должен сообщить о ней разработчикам. + +Есть два основных варианта проверки на такие ошибки: +* Исключение с кодом `LOGICAL_ERROR`. Его можно использовать для важных проверок, которые делаются в том числе в релизной сборке. +* `assert`. Такие условия не проверяются в релизной сборке, можно использовать для тяжёлых и опциональных проверок. + +Пример сообщения, у которого должен быть код `LOGICAL_ERROR`: +`Block header is inconsistent with Chunk in ICompicatedProcessor::munge(). It is a bug!` +По каким признакам можно заметить, что здесь говорится о внутренней программной ошибке? +* в сообщении упоминаются внутренние сущности из кода, +* в сообщении написано it's a bug, +* непосредственные действия пользователя не могут исправить эту ошибку. Мы ожидаем, что пользователь зарепортит её как баг, и будем исправлять в коде. + +### Как выбрать код ошибки? {#error-messages-choose} + +Код ошибки предназначен для автоматической обработки некоторых видов ошибок, подобно кодам HTTP. SQL стандартизирует некоторые коды, но на деле ClickHouse не всегда соответствует этим стандартам. Лучше всего выбрать существующий код из `ErrorCodes.cpp`, который больше всего подходит по смыслу. Можно использовать общие коды типа `BAD_ARGUMENTS` или `TYPE_MISMATCH`. Заводить новый код нужно, только если вы чётко понимаете, что вам нужна специальная автоматическая обработка конкретно этой ошибки на клиенте. Для внутренних программных ошибок используется код `LOGICAL_ERROR`. + +### Как добавить новое сообщение об ошибке? {#error-messages-add} + +Когда добавляете сообщение об ошибке: +1. Опишите, что произошло, в пользовательских терминах, а не кусками кода. +2. Добавьте максимум контекста (с чем произошло, когда, почему, и т.д.). +3. Добавьте типичные причины. +4. Добавьте варианты исправления (настройки, ссылки на документацию). +5. Вообразите дальнейшие действия пользователя. Ваше сообщение должно помочь ему решить проблему без использования отладочных инструментов и без чужой помощи. +6. Если сообщение об ошибке не формулируется в пользовательских терминах, и действия пользователя не могут исправить проблему -- это внутренняя программная ошибка, используйте код LOGICAL_ERROR или assert. + ## Платформа {#platforma} **1.** Мы пишем код под конкретные платформы. -- GitLab