Эти сообщения для других разработчиков
Ожидается, что эти сообщения будут прочитаны разработчиками, чтобы помочь им отладить приложение. Это может принимать две формы:
Активная отладка. Вы на самом деле запускаете отладчик, когда пишете код и пытаетесь выяснить, что происходит. В этом контексте полезное исключение поможет вам, упростив понимание того, что происходит не так, или в конечном итоге предложив обходной путь (хотя это необязательно).
Пассивная отладка. Код запускается в производство и дает сбой. Исключение регистрируется, но вы получаете только сообщение и трассировку стека. В этом контексте полезное сообщение об исключении поможет вам быстро локализовать ошибку.
Поскольку эти сообщения часто записываются в журнал, это также означает, что вы не должны включать в них конфиденциальную информацию (например, закрытые ключи или пароли, даже если это может быть полезно для отладки приложения).
Например, IOSecurityException
тип исключения, сгенерированного при записи файла, не очень ясно описывает проблему: это потому, что у нас нет прав доступа к файлу? Или, может быть, мы можем прочитать это, но не написать? Или, может быть, файл не существует, и у нас нет прав для создания файлов там? Или, может быть, он заблокирован (надеюсь, тип исключения в этом случае будет другим, но на практике типы могут иногда быть загадочными). Или, возможно, Code Access Security не позволяет нам выполнять какие-либо операции ввода-вывода?
Вместо:
IOSecurityException: файл был найден, но в разрешении на чтение его содержимого было отказано.
гораздо более явный Здесь мы сразу знаем, что права доступа к каталогу установлены правильно (иначе мы не сможем узнать, существует ли файл), но разрешения на уровне файла проблематичны.
Это также означает, что если вы не можете предоставить какую-либо дополнительную информацию, которой нет в типе исключения, вы можете оставить сообщение пустым. DivisionByZeroException
хороший пример, когда сообщение является избыточным С другой стороны, тот факт, что большинство языков позволяют генерировать исключение без указания его сообщения, делается по другой причине: либо потому, что сообщение по умолчанию уже доступно, либо потому, что оно будет сгенерировано позже, если это необходимо (и генерация этого сообщения). сообщение заключено в тип исключения, что имеет смысл, говоря "OOPly" ).
Обратите внимание, что по техническим (часто из-за производительности) причинам некоторые сообщения оказываются гораздо более загадочными, чем должны быть. .NET's NullReferenceException
:
В экземпляре объекта не задана ссылка на объект.
отличный пример сообщения, которое не помогает. Полезное сообщение будет:
Ссылка на объект product
не установлена на экземпляр объекта при вызове product.Price
.
Эти сообщения не для конечных пользователей!
Конечные пользователи не должны видеть сообщения об исключениях. Никогда. Хотя некоторые разработчики заканчивают тем, что показывают эти сообщения пользователям, это приводит к плохому пользовательскому опыту и расстройству. Сообщения, такие как:
В экземпляре объекта не задана ссылка на объект.
для конечного пользователя абсолютно ничего не значит, и его следует избегать любой ценой.
Наихудший сценарий - глобальная попытка / отлов, которая генерирует исключение для пользователя и выходит из приложения. Приложение, которое заботится о своих пользователях:
Обрабатывает исключения в первую очередь. Большинство из них могут быть обработаны, не мешая пользователю. Сеть не работает? Почему бы не подождать несколько секунд и повторить попытку?
Запрещает пользователю привести приложение к исключительному случаю. Если вы попросите пользователя ввести два числа и разделить первое на второе, почему вы позволите пользователю ввести ноль во втором случае, чтобы обвинить его несколько секунд спустя? Как насчет выделения текстового поля красным цветом (с полезной подсказкой о том, что число должно отличаться от нуля) и отключения кнопки проверки, пока поле не останется красным?
Предлагает пользователю выполнить действие в форме, которая не является ошибкой. Нет достаточных разрешений для доступа к файлу? Почему бы не попросить пользователя предоставить права администратора или выбрать другой файл?
Если больше ничего не работает, показывает полезную, дружескую ошибку, которая специально написана, чтобы уменьшить разочарование пользователя, помочь пользователю понять, что пошло не так и в конечном итоге решить проблему, а также помочь ему предотвратить ошибку в будущем (когда это применимо).
В вашем вопросе вы предложили иметь два сообщения в виде исключения: техническое для разработчиков и одно для конечных пользователей. Несмотря на то, что это допустимое предложение в некоторых незначительных случаях, большинство исключений создается на уровне, когда невозможно создать значимое сообщение для пользователей. Возьмите DivisionByZeroException
и представьте, что мы не можем предотвратить возникновение исключения и не можем справиться с этим сами. Когда происходит разделение, знает ли фреймворк (поскольку это фреймворк, а не бизнес-код, который выдает исключение), что будет полезным для пользователя сообщением? Точно нет:
Деление на ноль произошло. [ХОРОШО]
Вместо этого можно позволить ему выбросить исключение, а затем перехватить его на более высоком уровне, где мы знали бизнес-контекст и могли действовать соответствующим образом, чтобы реально помочь конечному пользователю, таким образом показывая что-то вроде:
Поле D13 не может иметь значение, идентичное значению в поле E6, поскольку вычитание этих значений используется в качестве делителя. [ХОРОШО]
или, может быть:
Значения, сообщаемые службой ATP, не соответствуют локальным данным. Это может быть вызвано несинхронизацией локальных данных. Хотите синхронизировать информацию о доставке и повторить попытку? [Да нет]
Эти сообщения не для анализа
Сообщения об исключениях не должны анализироваться или использоваться программно. Если вы считаете, что вызывающей стороне может потребоваться дополнительная информация, включите ее в исключение рядом с сообщением. Это важно, потому что сообщение может быть изменено без уведомления. Тип является частью интерфейса, но сообщения нет: никогда не полагайтесь на него для обработки исключений.
Представьте себе сообщение об исключении:
Время ожидания подключения к серверу кэширования истекло после ожидания 500 мс. Либо увеличьте время ожидания, либо проверьте мониторинг производительности, чтобы определить падение производительности сервера. Среднее время ожидания кеширующего сервера составило 6 мс. за последний месяц 4 мс за последнюю неделю и 377 мс. за последний час.
Вы хотите извлечь значения «500», «6», «4» и «377». Подумайте немного о подходе, который вы будете использовать для анализа, и только потом продолжайте чтение.
У тебя есть идея? Отлично.
Теперь оригинальный разработчик обнаружил опечатку:
Connecting to the caching sever timed out after waiting [...]
должно быть:
↓
Connecting to the caching server timed out after waiting [...]
Более того, разработчик считает, что месяц / неделя / один час не особенно актуальны, поэтому он также вносит дополнительные изменения:
Среднее время ожидания кеширующего сервера составило 6 мс. за последний месяц 5 мс за последние 24 часа 377 мс за последний час.
Что происходит с вашим разбором?
Вместо синтаксического анализа вы можете использовать свойства исключений (которые могут содержать все, что угодно, как только данные могут быть сериализованы):
{
message: "Connecting to the caching [...]",
properties: {
"timeout": 500,
"statistics": [
{ "timespan": 1, "unit": "month", "average-timeout": 6 },
{ "timespan": 7, "unit": "day", "average-timeout": 4 },
{ "timespan": 1, "unit": "hour", "average-timeout": 377 },
]
}
}
Насколько легко использовать эти данные сейчас?
Иногда (например, в .NET) сообщение может даже быть переведено на язык пользователя (IMHO, перевод этих сообщений абсолютно неверен, поскольку любой разработчик, как ожидается, сможет читать на английском языке). Разбор таких сообщений практически невозможен.