В настоящее время я делаю обзор кода, и одна из вещей, на которые я обращаю внимание, - это число исключений, когда сообщение об исключении, кажется, просто повторяет, где произошло исключение. например
throw new Exception("BulletListControl: CreateChildControls failed.");
Все три пункта в этом сообщении я могу отработать из остальных исключений. Я знаю класс и метод из трассировки стека, и я знаю, что это не удалось (потому что у меня есть исключение).
Это заставило меня задуматься о том, какое сообщение я помещаю в сообщения об исключениях. Сначала я создаю класс исключения, если один уже не существует, по общей причине (например PropertyNotFoundException
- почему ), а затем , когда я бросаю его сообщение указывает на то , что пошло не так (например , «Не удалось найти свойство„IDontExist“на узле 1234 "- то, что ). Где находится в StackTrace
. , Когда может закончиться в журнале (если применимо). Как для разработчика , чтобы работать (и исправить)
Есть ли у вас какие-либо другие советы по выбрасыванию исключений? Особенно в отношении создания новых типов и сообщений об исключениях.
источник
Ответы:
Я направлю свой ответ больше на то, что происходит после исключения: для чего оно хорошо и как должно вести себя программное обеспечение, что должны делать ваши пользователи с исключением? Отличная техника, с которой я столкнулся в начале своей карьеры, состояла в том, чтобы всегда сообщать о проблемах и ошибках в 3 частях: контекст, проблема и решение. Использование этой линии значительно меняет обработку ошибок и делает программное обеспечение намного лучше для операторов.
Вот несколько примеров.
В этом случае оператор точно знает, что делать и к какому файлу это относится. Они также знают, что изменения пула соединений не выполнялись и должны быть повторены.
Я пишу серверные системы, и мои операторы, как правило, хорошо разбираются в технической поддержке. Я написал бы сообщения по-другому для настольных программ, которые имеют другую аудиторию, но содержат ту же информацию.
Несколько замечательных вещей случаются, если использовать эту технику. Разработчик программного обеспечения часто лучше всех знает, как решать проблемы в своем собственном коде, поэтому кодирование решений таким образом, когда вы пишете код, приносит огромную пользу конечным пользователям, находящимся в затруднительном положении при поиске решений, поскольку они часто упускают информацию о что именно делает программное обеспечение. Любой, кто когда-либо читал сообщение об ошибке Oracle, поймет, что я имею в виду.
Вторая замечательная вещь, которая приходит на ум, - это когда вы пытаетесь описать решение в своем исключении и пишете «Проверьте X, и если A, то B, еще C». Это очень четкий и очевидный признак того, что ваше исключение проверяется не в том месте. У вас, программиста, есть возможность сравнивать вещи в коде, поэтому «если» операторы должны выполняться в коде, зачем вовлекать пользователя в то, что можно автоматизировать? Скорее всего, это из-за более глубокого в коде, и кто-то сделал ленивую вещь и выбросил IOException из любого числа методов и уловил потенциальные ошибки от всех из них в блоке вызывающего кода, который не может адекватно описать, что пошло не так, что конкретноеконтекст есть и как это исправить. Это побуждает вас писать более мелкие ошибки, отслеживать и обрабатывать их в нужном месте вашего кода, чтобы вы могли правильно сформулировать шаги, которые должен предпринять оператор.
В одной компании у нас были первоклассные операторы, которые действительно хорошо знали программное обеспечение и вели свою собственную «рабочую книгу», которая дополняла наши отчеты об ошибках и предлагаемые решения. Чтобы распознать это, программное обеспечение начало включать вики-ссылки на рабочую книгу в исключениях, чтобы было доступно базовое объяснение, а также ссылки на более продвинутые обсуждения и наблюдения операторов со временем.
Если у вас была возможность попробовать эту технику, становится гораздо более очевидным, как вы должны называть свои исключения в коде при создании своих собственных. NonRecoverableConfigurationReadFailedException становится небольшим сокращением для того, что вы собираетесь более полно описать оператору. Мне нравится быть многословным, и я думаю, что следующему разработчику, который прикоснется к моему коду, будет легче интерпретировать.
источник
FileNotFound
илиConnectException
вы знаете, что делать))В этом более новом вопросе я подчеркнул, что исключения не должны содержать сообщения вообще. На мой взгляд, тот факт, что они делают, является огромным заблуждением. Я предлагаю то, что
Исключение должно содержать в своих переменных-членах как можно больше подробностей о том, что именно произошло; например,
IndexOutOfRangeException
должен содержать значение индекса, который был признан недействительным, а также верхнее и нижнее значения, которые действовали в момент, когда было сгенерировано исключение. Таким образом, используя отражение, вы можете автоматически создать сообщение, которое будет выглядеть следующим образом:IndexOutOfRangeException: index = -1; min=0; max=5
и вместе с трассировкой стека это должна быть вся объективная информация, необходимая для устранения проблемы. Форматирование его в красивое сообщение типа «индекс -1 не было между 0 и 5» не добавляет никакого значения.В вашем конкретном примере
NodePropertyNotFoundException
класс будет содержать имя свойства, которое не было найдено, и ссылку на узел, который не содержит этого свойства. Это важно: оно не должно содержать имя узла; он должен содержать ссылку на фактический узел. В вашем конкретном случае это может быть необязательно, но это принципиальный вопрос и предпочтительный способ мышления: главная задача при создании исключения состоит в том, что оно должно быть использовано кодом, который может его перехватить. Удобство использования людьми является важной, но только вторичной проблемой.Это учитывает очень неприятную ситуацию, с которой вы, возможно, сталкивались в какой-то момент своей карьеры, когда вы могли поймать исключение, содержащее важную информацию о том, что произошло в тексте сообщения, но не в его переменных-членах, поэтому вы пришлось разбирать текст строки, чтобы выяснить, что произошло, надеясь, что текст сообщения останется прежним в будущих версиях нижележащего слоя, и молясь о том, чтобы текст сообщения не был на каком-то иностранном языке, когда ваша программа бегать в другие страны.
Конечно, поскольку имя класса исключения является сообщением исключения (а переменные-члены исключения являются конкретными деталями), это означает, что вам нужно много-много разных исключений для передачи всех различных сообщений, и это нормально.
Теперь, иногда, когда мы пишем код, мы сталкиваемся с ошибочной ситуацией, для которой мы просто хотим быстро кодировать
throw
инструкцию и продолжать писать наш код вместо того, чтобы прерывать то, что мы делаем, чтобы создать новый класс исключений, чтобы мы могли брось это прямо там. Для этих случаев у меня естьGenericException
класс, который на самом деле принимает строковое сообщение в качестве параметра времени создания, но конструктор этого класса исключений украшен огромным огромным ярко-фиолетовымFIXME XXX TODO
комментарием, утверждающим, что каждый экземпляр этого класса должен быть заменено созданием некоторого более специализированного класса исключений перед выпуском системы программного обеспечения, предпочтительно перед фиксацией кода.источник
node
объект защищен предложением using-disable (в C #) или try-with-resources (в Java): объект, сохраненный с исключением, будет удален / закрыт, что сделает его недопустимым получить доступ к нему, чтобы получить любую полезную информацию из него в месте обработки исключения. Я полагаю, что в этих случаях некоторая сводка объекта должна храниться в исключении, а не в самом объекте. Я не могу думать о безошибочном способе универсально обращаться с этим для всех случаев.Как правило, исключение должно помочь разработчикам точно определить причину , предоставив полезную информацию (ожидаемые значения, фактическое значение, возможные причины / решение и т. Д.).
Новые типы исключений должны создаваться, когда ни один из встроенных типов не имеет смысла . Определенный тип позволяет другим разработчикам перехватывать определенное исключение и обрабатывать его. Если разработчик будет знать, как обрабатывать ваше исключение, но с типом
Exception
, он не сможет обработать его должным образом.источник
В .NET никогда не
throw new Exception("...")
бывает (как показал автор вопроса). Исключение является корневым типом исключения и, как предполагается, никогда не генерируется напрямую. Вместо этого бросьте один из производных типов исключений .NET или создайте свое собственное пользовательское исключение, которое является производным от исключения (или другого типа исключения).Почему бы не бросить исключение? Потому что создание Exception ничего не делает для описания вашего исключения и вынуждает ваш вызывающий код писать код,
catch(Exception ex) { ... }
который, как правило, не очень хорошая вещь! :-).источник
То, что вы хотите найти, чтобы «добавить» исключение, это те элементы данных, которые не присущи исключению или трассировке стека. Являются ли они частью «сообщения» или должны быть прикреплены при регистрации - интересный вопрос.
Как вы уже заметили, исключение, вероятно, говорит вам, что, трассировка стека, вероятно, говорит вам, где, но «почему» может быть более вовлечено (должно быть, можно надеяться), чем просто смотреть на строку или две и говорить « дох! конечно ". Это еще более верно при регистрации ошибок в производственном коде - меня слишком часто кусают плохие данные, попадающие в живую систему, которой нет в наших тестовых системах. Это так же просто, как узнать, какой идентификатор у записи в базе данных, которая вызывает (или способствует) ошибку, может сэкономить значительное количество времени.
Итак ... Либо перечислены, либо, для .NET, добавлены в сбор данных зарегистрированных исключений (cf @Plip!):
Некоторые вещи, конечно, вы не будете знать, что вам нужно, пока их нет в вашем первоначальном отчете / журнале ошибок. Некоторые вещи, которые вы не понимаете, вы можете получить, пока не обнаружите, что они вам нужны.
источник
Какие исключения для ?
(1) Сказать пользователю что-то пошло не так?
Это должно быть последним средством, потому что ваш код должен вмешиваться и показывать им что-то «лучше», чем исключение.
Сообщение об ошибке должно четко и кратко содержать информацию о том, что пошло не так и что, если что-либо, пользователь может сделать для восстановления после ошибки.
например, «Пожалуйста, не нажимайте эту кнопку снова»
(2) Сообщать разработчику, когда что-то пошло не так?
Это то, что вы входите в файл для последующего анализа. Трассировка стеки покажет Застройщик , где коды сломали; сообщение должно, опять же, указать, что пошло не так.
(3) Сообщать обработчику исключений (т.е. коду), что что-то пошло не так?
Тип исключения будут решать , какие исключения обработчик получит смотреть на него и свойства , определенные на объект Exception позволит обработчик иметь дело с ним.
Сообщение Исключения совершенно не имеет значения .
источник
Не создавайте новые типы, если вы можете помочь. Они могут вызвать дополнительную путаницу, сложность и привести к большему количеству кода для обслуживания. Они могут заставить ваш код расширяться. Разработка иерархии исключений требует много усилий и тестирования. Это не мысль после. Часто лучше использовать встроенную иерархию исключений языка.
Содержание сообщения об исключении зависит от получателя сообщения, поэтому вы должны поставить себя на место этого человека.
Инженер службы поддержки должен быть в состоянии определить источник ошибки как можно быстрее. Включите короткую описательную строку плюс любые данные, которые могут помочь в устранении проблемы. Всегда включайте трассировку стека - если вы можете - это будет единственный истинный источник информации.
Представление ошибок обычным пользователям вашей системы зависит от типа ошибки: если пользователь может решить проблему, например, предоставив различные входные данные, требуется краткое описательное сообщение. Если пользователь не может решить проблему, лучше указать, что произошла ошибка, и зарегистрировать / отправить ошибку в службу поддержки (используя приведенные выше рекомендации).
Кроме того - не бросайте большую «ОШИБКУ ХАЛТА!» икона. Это ошибка - это не конец света.
Итак, подведем итоги: подумайте об актерах и сценариях использования вашей системы. Поставьте себя на место этого пользователя. Быть полезным. Будь милым Подумайте об этом заранее в дизайне вашей системы. С точки зрения ваших пользователей - эти случаи исключений и то, как система обрабатывает их, так же важны, как и обычные случаи в вашей системе.
источник