Почему многие сообщения об исключениях не содержат полезных сведений?

Похоже, что существует определенное соглашение о том, что сообщения об исключениях должны содержат полезные сведения .

Почему многие общие исключения из системных компонентов не содержат полезных сведений?

Несколько примеров:

  • .NET List индексный доступ ArgumentOutOfRangeException not сообщит мне значение индекса, которое было проверено и недействительно, и не сообщает мне допустимый диапазон.
  • В основном все сообщения об исключениях из стандартной библиотеки MSVC C ++ совершенно бесполезны (в том же духе, что и выше).
  • Исключения Oracle в .NET, рассказывающие вам (перефразируемые) «TABLE ИЛИ VIEW not found», но не , который один.

Итак, мне кажется, что в большинстве случаев сообщения не содержат достаточные сведения, чтобы быть полезными. Неужели мои ожидания не оправдались? Я использую исключения неправильно, что я даже заметил это? Или, может быть, мое впечатление неверно: большинство исключений do действительно предоставляют полезные сведения?

209 голосов | спросил Martin Ba 13 PMpMon, 13 Apr 2015 17:21:16 +030021Monday 2015, 17:21:16

9 ответов


198

Исключения не содержат полезных деталей, поскольку концепция исключений еще недостаточно созрела в дисциплине программирования, поэтому многие программисты не понимают их полностью, и поэтому они не относятся к ним должным образом.

Да, IndexOutOfRangeException должен содержать точный индекс, который был вне диапазона, а также диапазон, который был действителен в момент его броска, и он является презренным от имени создателей время выполнения .NET, которого нет. Да, исключение Oracle или представление не найденное должно содержать имя таблицы или представления, которое не было найдено, и опять же тот факт, что это не так, является презренным от имени того, кто несет ответственность за это.

В значительной степени путаница проистекает из ошибочной исходной идеи о том, что исключения должны содержать человеко-читаемые сообщения, что, в свою очередь, связано с отсутствием понимания того, что такое исключения, поэтому это порочный круг.

Поскольку люди думают, что в исключении должно содержаться человеко-читаемое сообщение, они считают, что любая информация, содержащаяся в этом исключении, также должна быть отформатирована в человеко-читаемом сообщении, а затем им либо надоедают писать все человеко- читаемый код построения сообщений, или они опасаются, что это может разглашать непредвиденный объем информации, какой бы любопытный взгляд мог видеть сообщение. (Проблемы безопасности, упомянутые в других ответах.)

Но дело в том, что они не должны беспокоиться об этом, потому что исключение должно not содержать человеко-читаемое сообщение. Исключения - это вещи, которые только программисты должны видеть и /или иметь дело. Если когда-либо возникает необходимость представлять информацию о сбоях пользователю, это должно выполняться на очень высоком уровне сложным образом и на языке пользователя, что, по статистике, вряд ли будет английским.

Итак, для нас, программистов, «сообщение» исключения - это имя класса исключения , и любая другая информация, относящаяся к исключению, должна быть скопирована в (final /readonly) переменные-члены объекта исключения. Предпочтительно, каждый из его возможных немногочисленных. Таким образом, ни одно сообщение не должно генерироваться (или должно быть), и поэтому никакие любопытные глаза не видят его.

Чтобы выразить обеспокоенность, высказанную Томасом Оуэнсом, в комментарии ниже:

Да, конечно, на каком-то уровне вы создадите сообщение журнала об исключении. Но вы уже видите проблему с тем, что вы говорите: с одной стороны, сообщение журнала исключений без трассировки стека бесполезно, но, с другой стороны, вы не хотите, чтобы пользователь видел всю трассировку стека исключений. Опять же, наша проблема заключается в том, что наша перспектива искажается традиционными практиками. Файлы журналов традиционно были в обычном тексте, что, возможно, было прекрасным, пока наша дисциплина находилась в зачаточном состоянии, но, возможно, не больше: если есть проблема с безопасностью, тогда файл журнала должен быть двоичным и /или зашифрованным.

Будь бинарный или обычный текст, файл журнала следует рассматривать как поток, в который приложение выполняет сериализацию отладочной информации. Такой поток будет только для глаз программистов, и задача генерации информации об отладке для исключения должна быть такой же простой, как сериализация исключения в поток журнала отладки. Таким образом, просматривая журнал, вы можете увидеть имя класса исключения (которое, как я уже сказал, является для всех практических целей «сообщением») каждой из переменных-членов исключения, которые описывают все, что уместно, и-практический-to-include-in-a-log, и всю трассировку стека. Обратите внимание на то, что форматирование сообщения исключения для человека, видимого отсутствует из этого процесса.

P.S.

Несколько других моих мыслей по этому вопросу можно найти в этом ответе: Как написать сообщение о хорошем исключении

P.P.S.

Похоже, что мое предложение о бинарных файлах журналов было отброшено многими людьми, поэтому я еще раз поправил ответ, чтобы еще более ясно, что здесь я предлагаю не что файл журнала должен быть двоичным, но при необходимости файл журнала может быть двоичным.

ответил Mike Nakis 13 PMpMon, 13 Apr 2015 19:13:40 +030013Monday 2015, 19:13:40
44
  

Почему многие общие исключения из системных компонентов не содержат полезных сведений?

По моему опыту, существует ряд причин, по которым исключения не содержат полезной информации. Я ожидаю, что подобные причины будут применяться и к компонентам системы, но я точно не знаю.

  • Люди, ориентированные на безопасность, видят исключения как источник утечки информации (для примера ). Поскольку поведение исключений по умолчанию заключается в том, чтобы отображать эту информацию для пользователя, программисты иногда ошибаются со стороны осторожности.
  • В C ++ я слышал аргументы против выделения памяти в блоках catch (где, по крайней мере, некоторый контекст для создания хороших сообщений лежит). Это распределение трудно справиться и, что еще хуже, может вызвать исключение из памяти - часто сбой вашего приложения или утечка памяти. Трудно правильно отформатировать исключения, не выделяя память, и эта практика могла мигрировать между языками, как это делают программисты.
  • Они не знают. Я имею в виду, существуют сценарии , где код имеет нет идею, что пошло не так. Если код не знает - он не может вам сказать.
  • Я работал в тех местах, где проблемы локализации помешали помещать только английские строки в систему - даже для исключений, которые будут прочитаны только англоязычным персоналом поддержки.
  • В некоторых местах, я видел исключения, более похожие на утверждения. Они должны дать четкое, громкое сообщение во время разработки, что что-то не сделано, или изменения были сделаны в одном месте, но не в другом. Они часто достаточно уникальны, что хорошее сообщение будет дублировать усилия или просто запутывать.
  • Люди ленивы, программисты больше, чем большинство. Мы тратим гораздо меньше времени на исключительный путь, чем на счастливый путь, и это побочный эффект.
  

Ожидаются ли мои ожидания? Я неправильно использую Исключения, что я даже заметил это?

Любопытное? Я имею в виду, что исключения должны иметь приятные сообщения, но они также являются исключениями . Вы должны тратить свое время на разработку кода, чтобы избежать исключительных условий, или писать код для обработки исключительных условий (игнорируя сообщение), не используя их в качестве своего рода интерактивного механизма обратной связи при кодировании. Непременно использовать их для целей отладки, но в большинстве ситуаций это должно быть сведено к минимуму. То, что вы заметили эту проблему, заставляет меня беспокоиться о том, что вы не выполняете достаточно хорошую работу по их предотвращению.

ответил Telastyn 13 PMpMon, 13 Apr 2015 18:54:36 +030054Monday 2015, 18:54:36
12

У меня нет избытка опыта C # или C ++, но я могу сказать вам это - написанные разработчиком исключения 9 из 10 раз более полезны, чем любое общее исключение, которое вы когда-либо найдете, период.

В идеале да, общее исключение укажет вам именно на то, почему возникла ошибка, и вы сможете исправить ее с легкостью, но реалистично, в больших приложениях с несколькими классами, которые могут генерировать множество различных исключений , или те же исключения, всегда более полезно писать собственный вывод для возврата ошибки, чем полагаться на сообщение по умолчанию.

Вот как это должно быть, потому что, как указывали многие люди, некоторые приложения не хотят бросать сообщение об ошибке, которое они не хотят видеть, по соображениям безопасности или не путать их.

Вместо этого вы должны предвидеть в своем дизайне, какие типы ошибок могут возникать в вашем приложении (и всегда будут ошибки) и писать сообщения об ошибках, которые помогут вам определить проблему.

Это не всегда поможет вам, потому что вы не можете всегда ожидать, какое сообщение об ошибке будет полезно, но это первый шаг к лучшему пониманию вашего приложения в долгосрочной перспективе.

ответил Zibbobz 13 PMpMon, 13 Apr 2015 20:13:36 +030013Monday 2015, 20:13:36
7

Вопрос заключается в конкретном вопросе, почему так много исключений, вызванных «системными компонентами» (также стандартными библиотечными классами), не содержат полезных сведений.

К сожалению, большинство разработчиков не пишут основные компоненты в стандартных библиотеках, равно как и подробные проектные документы или другое обоснование дизайна обязательно публикуются. Другими словами, мы, возможно, никогда не узнаем наверняка.

Однако есть два ключевых момента, которые следует учитывать, почему подробная информация об исключении может быть нежелательной или важной:

  1. Исключение может быть использовано путем вызова кода любым способом: стандартная библиотека не может устанавливать ограничения на использование исключения. В частности, он может отображаться пользователю. Рассмотрим индекс массива за пределами границ: это может дать полезную информацию злоумышленнику. Дизайнер языка понятия не имеет, как приложение будет использовать брошенное исключение или даже какой тип приложения (например, веб-приложение или рабочий стол), поэтому исключение информации может быть более безопасным с точки зрения безопасности.

  2. Исключения не должны отображаться пользователю. Вместо этого отобразите дружественное сообщение об ошибке и запишите исключение в место, где злоумышленник не имеет доступа (если применимо). Как только ошибка будет идентифицирована, разработчик должен отлаживать код, проверять стековые фреймы и логические пути. На данный момент разработчик имеет больше информации, чем может когда-либо надеяться исключение.

ответил 13 PMpMon, 13 Apr 2015 18:41:40 +030041Monday 2015, 18:41:40
4

Во-первых, позвольте мне взломать пузырь, сказав, что даже если сообщение diag загружается информацией, которая приведет вас к точной строке кода и подкоманде через 4 секунды, скорее всего, пользователи никогда не запишут ее или не передадут люди поддержки, и вам скажут: «Ну, это что-то говорит о нарушении ... Я не знаю, что это выглядело сложным!»

Я уже более 30 лет пишу программное обеспечение и поддерживаю результаты других программ, и лично, текущее качество сообщения об исключении практически не имеет ничего общего с безопасностью, независимо от того, как закончились конечные результаты их модель вселенной, гораздо больше связана с тем фактом, что многие в нашей отрасли изначально были самоучкой, и они просто никогда не включали уроки коммуникации. Возможно, если бы мы НАПРАВИЛИ всех новых кодеров в позиции обслуживания на пару лет, когда им приходилось иметь дело с выяснением того, что пошло не так, они понимали бы важность хотя бы некоторой формы точности.

Недавно в восстановленном приложении было принято решение, что коды возврата попадут в одну из трех групп:

  • От 0 до 9 будет успешным благодаря успеху с дополнительными Информация.
  • От 10 до 99 будет не смертельным (восстанавливаемым) ошибок и
  • с 101 по 255 будут фатальными ошибками.

(100 по какой-то причине не учитывается)

В любом конкретном рабочем процессе наша мысль была повторно использована, или общий код использовал бы общие возвраты (> 199) для фатальных ошибок, оставив нам 100 фатальных ошибок, возможных для рабочего потока. При незначительном различии данных в сообщении ошибки, такие как не найденный файл, могут использовать один и тот же код и различать сообщения.

Когда код вернулся от подрядчиков, вы не поверили бы нашему удивлению, когда практически каждый Одиночный FATAL ERROR был кодом возврата 101.

Все, что считало, что я думаю, что ответ на ваш вопрос состоит в том, что сообщения настолько бессмысленны, потому что, когда они были созданы, они должны были быть заполнителями, которых никто не возвращал. В конце концов, люди выяснили, как исправить проблемы не из-за сообщений, а для DISPITE.

С тех пор у самообученных людей просто никогда не было хорошего примера того, что должно содержать исключение. Добавьте к этому, что больше пользователей не читают сообщения, а тем более пытаются передать их на поддержку (я видел сообщения об ошибках, которые были вырезаны и вставляются используемыми, которые затем были отредактированы перед отправкой с последующим комментарием, что это казалось, было много информации, и я не мог этого хотеть, поэтому они случайно удалили кучу этого.

И давайте посмотрим правде в глаза, слишком много (не все, но слишком много) из следующего поколения кодеров, если это больше работает и не добавляет флеш, просто не стоит ...

Последнее примечание: если сообщение об ошибке содержит код ошибки /возврата, мне кажется, что где-то в исполняемых модулях должна быть строка, которая читает что-то вроде «if condition return code-value», и условие должно сказать вам, почему произошел код возврата. Это похоже на простой логический подход, но для жизни меня просто ПОПРОБУЙТЕ, чтобы Microsoft сообщила вам, что произошло, когда обновление Windows не удалось на CODE 80241013 или какой-либо другой очень уникальный идентификатор. Какая грусть, не так ли?

ответил Randy 14 AMpTue, 14 Apr 2015 09:52:20 +030052Tuesday 2015, 09:52:20
3

Хотя я согласен с тем, что исключения должны содержать как можно больше информации или, по крайней мере, быть менее общим. В таблице, не найденном, имя таблицы было бы приятным.

Но вы знаете больше о том, что вы пытались сделать в месте в коде, где вы получили исключение. Хотя часто вы действительно не можете многое сделать, чтобы исправить ситуацию, когда что-то пошло не так в библиотеке вне вашего контроля, вы можете добавить гораздо более полезную информацию о том, в какой ситуации что-то пошло не так.

Если таблица не найдена, это не поможет вам, если вам скажут, что таблица, которая не может быть найдена, называется СТУДЕНТОМ, потому что у вас нет такой таблицы, и эта строка нигде в вашем коде.

Но если вы поймаете исключение и свернете его с помощью SQL-оператора, который вы пытаетесь выполнить, вам будет лучше, так как оказывается, что вы пытались вставить запись с полем имени Robert '); СТРУКТУРА СТРУКТУРЫ DROP; (всегда есть xkcd!)

Итак, чтобы бороться с менее информативными исключениями: try-catch-rethrow с большей информацией, специфичной для того, что вы пытались сделать.

Я, вероятно, должен добавить, поскольку это будет скорее ответом на вопрос о том, почему в вопросе, что вероятная причина, по которой фокус со стороны создателей библиотек не заключался в улучшении сообщений об исключениях, заключается в том, что они не знаю, почему что-то было пробовано, что не удалось, эта логика находится в вызывающем коде.

ответил Bent 14 AMpTue, 14 Apr 2015 11:52:18 +030052Tuesday 2015, 11:52:18
3

Чтобы дать немного другой ответ: Код ошибки, вероятно, был сделан для спецификации:

  • Функция принимает X и возвращает Y
  • Если X недействителен, выберите исключение Z

Добавьте давление, чтобы доставить точно в спецификацию (из-за боязни отклонения в обзоре /тестировании) за минимальное время и с минимальной суматохой, тогда у вас есть рецепт для полностью совместимого и бесполезного исключения библиотеки.

ответил Stu Pegg 15 AMpWed, 15 Apr 2015 00:12:59 +030012Wednesday 2015, 00:12:59
3

Исключения имеют стоимость, специфичную для языка и реализации.

Например, исключения C ++ необходимы для уничтожения всех живых данных между бросанием кадра вызова и захватом кадра вызова, и это дорого. Следовательно, программисты не хотят часто использовать исключения.

В Ocaml исключение бросается почти так же быстро, как C setjmp (его стоимость не зависит от количества пройденных кадров вызова), поэтому разработчики могут использовать его в большом количестве (даже для не- -эксклюзивные, очень распространенные случаи). Напротив, исключения C ++ достаточно тяжелы, поэтому вы, вероятно, не будете использовать их так же, как в Ocaml.

Типичным примером является некоторый рекурсивный поиск или исследование, которое может быть «остановлено» внутри довольно глубокой рекурсии (например, найти лист в дереве или функцию унификации). На некоторых языках быстрее (так более идиоматично) распространять это условие на каждого абонента. На других языках сброс исключения выполняется быстрее.

Таким образом, в зависимости от языка (и привычек разработчиков, использующих его) исключение может содержать много полезных деталей или, наоборот, использоваться как быстрый нелокальный переход и переносить только очень полезные данные.

ответил Basile Starynkevitch 14 AMpTue, 14 Apr 2015 10:03:00 +030003Tuesday 2015, 10:03:00
-2

Что заставляет вас думать, что значение индекса или требуемый диапазон или имя таблицы является полезной деталью для исключения?

Исключения не являются механизмом обработки ошибок; они являются механизмом восстановления восстановления .

Точка исключений - это пузырь до уровня кода, который может обрабатывать исключение. Где бы ни находился этот уровень, либо у вас есть необходимая информация, либо это не имеет значения. Если вам нужна информация, но у вас нет доступа direct , вы не обрабатываете исключение на соответствующем уровне.

Единственный раз, когда я могу подумать о том, какая дополнительная информация могла бы быть полезной, находится на абсолютном верхнем уровне вашего приложения, где вы выходите из строя и испускаете ошибку; но это не является задачей исключения для доступа, компиляции и хранения этой информации.

Я не говорю, что вы можете просто «выбросить новое исключение» повсюду и называть его хорошим, можно писать плохие исключения. Но включение нерелевантной информации не является необходимым для их правильного использования.

ответил Odalrick 15 PMpWed, 15 Apr 2015 14:13:21 +030013Wednesday 2015, 14:13:21

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132