Я пишу простую небольшую программу для передачи MIDI по сети. Я знаю, что программа столкнется с проблемами передачи и / или другими исключительными ситуациями, которые я не смогу предсказать.
Для обработки исключений я вижу два подхода. Должен ли я написать программу так, чтобы она:
- терпит неудачу с ударом, когда что-то идет не так или
- Должен ли он просто игнорировать ошибку и продолжать, за счет целостности данных?
Какой подход разумно ожидать от пользователя?
Есть ли лучший способ обработки исключений?
Кроме того, должно ли мое решение об обработке исключений зависеть от того, имею ли я дело с сетевым подключением (т. Е. Что-то, где я могу разумно ожидать возникновения проблем)?
exception-handling
Арлен Бейлер
источник
источник
Ответы:
Никогда не следует игнорировать ошибку, с которой сталкивается ваша программа. Как минимум, вы должны записать его в файл или другой механизм для уведомления. Там могут быть случайные ситуации , когда вы хотите , чтобы игнорировать ошибку , но документально это! Не пишите пустой
catch
блок без комментариев, объясняющих, почему он пуст.Должна ли программа потерпеть неудачу или нет, во многом зависит от контекста. Если вы можете обработать ошибку изящно, сделайте это. Если это непредвиденная ошибка, ваша программа потерпит крах. Это в значительной степени основа обработки исключений.
источник
Вы никогда не должны молча игнорировать ошибки, потому что ваша программа построена на серии действий, которые неявным образом зависят от всего, что было сделано до их исправления. Если на шаге 3 что-то пойдет не так, и вы попытаетесь перейти к шагу 4, шаг 4 будет начинаться на основе неверных предположений, что повышает вероятность того, что он также приведет к возникновению ошибки. (И если вы проигнорируете это тоже, то шаг 5 выдает ошибку, и оттуда вещи начнут расти как снежный ком.)
Дело в том, что по мере накопления ошибок в конечном итоге вы столкнетесь с такой большой ошибкой, что не сможете ее игнорировать, потому что она будет состоять из чего-то, что дается пользователю, и что это будет совершенно неправильно. Тогда у вас есть пользователи, которые жалуются на то, что ваша программа не работает должным образом, и вы должны это исправить. И если часть «дать что-то пользователю» находится на шаге 28, и вы не представляете, что первоначальная ошибка, которая привела ко всему этому беспорядку, была на шаге 3, потому что вы проигнорировали ошибку на шаге 3, вы получите черт возьми, отладка проблемы!
С другой стороны, если эта ошибка на шаге 3 приводит к тому, что все вспыхивает на лице пользователя, и генерирует ошибку, говоря
SOMETHING WENT BADLY WRONG IN STEP 3!
(или ее технический эквивалент, трассировка стека), то результат будет тем же - пользователь жаловался на вас программа не работает должным образом - но на этот раз вы точно знаете, с чего начать, когда будете ее исправлять .РЕДАКТИРОВАТЬ: В ответ на комментарии, если что-то идет не так, как вы ожидали и знаете, как справиться, это другое. Например, в случае получения искаженного сообщения это не является ошибкой программы; это «пользователь предоставил неверный ввод, который не прошел проверку». Соответствующий ответ - сообщить пользователю, что он вводит вам недопустимые данные, как, по вашему мнению, вы и делаете. Нет необходимости аварийно завершать работу и генерировать трассировку стека в таком случае.
источник
Есть и другие варианты между «взорвать» и «игнорировать».
Если ошибка предсказуема и ее можно избежать, измените дизайн или измените код, чтобы избежать ее.
Если ошибка предсказуема, но ее невозможно избежать, но вы знаете, что делать, когда это произойдет, то поймайте ошибку и обработайте ситуацию. Но будьте осторожны, чтобы не использовать исключения в качестве управления потоком. И вы можете захотеть записать предупреждение в этот момент, и, возможно, уведомить пользователя, если есть какие-то действия, которые он может предпринять, чтобы избежать этой ситуации в будущем.
Если ошибка предсказуема, неизбежна, и когда она случается, вы ничего не можете сделать, чтобы гарантировать целостность данных, тогда вам нужно зарегистрировать ошибку и вернуться в безопасное состояние (что, как говорили другие, может означать сбой).
Если ошибка не та, которую вы ожидали, то вы действительно не можете быть уверены, что можете даже вернуться в безопасное состояние, поэтому лучше всего просто войти в систему и завершиться сбоем.
Как правило, не поймайте никаких исключений, с которыми вы ничего не можете сделать, если только вы не планируете регистрировать и перебрасывать их. И в тех редких случаях, когда try-catch-ignore неизбежен, по крайней мере, добавьте комментарий в свой блок catch, чтобы объяснить, почему.
См . Превосходную статью Эрика Липперта по обработке исключений для получения дополнительных предложений по категоризации и обработке исключений.
источник
Вот мои взгляды на вопрос:
Хороший стартовый принцип - быстро провалиться. В частности, вы никогда не должны писать код обработки ошибок для любого сбоя, для которого вы не знаете точную причину.
После применения этого принципа вы можете добавить код восстановления для определенных ошибок, с которыми вы сталкиваетесь. Вы также можете ввести несколько «безопасных состояний» для возврата. Прерывание программы в большинстве случаев безопасно, но иногда вы можете захотеть вернуться в другое известное исправное состояние. Примером является то, как современная ОС обрабатывает нарушающую программу. Это только закрывает программу, а не всю ОС.
Быстро и медленно покрывая все более и более конкретные ошибки, вы никогда не нарушите целостность данных и неуклонно продвигаетесь к более стабильной программе.
Поглощение ошибок, то есть попытка спланировать ошибки, для которых вы не знаете точную причину и, следовательно, не имеете конкретной стратегии восстановления, приводит только к увеличению количества пропускаемых ошибок и обхода кода в вашей программе. Так как нельзя доверять тому, что предыдущие данные были правильно обработаны, вы начнете видеть разбросанные проверки на неверные или отсутствующие данные. Ваша цикломатическая сложность выйдет из-под контроля, и вы получите большой шарик грязи.
Знаете ли вы о случаях неудач или нет, это не так важно. Но если вы, например, имеете дело с сетевым подключением, для которого вы знаете определенное количество состояний ошибок, отложите добавление обработки ошибок до тех пор, пока не добавите код восстановления. Это соответствует принципам, изложенным выше.
источник
Вы никогда не должны молча игнорировать ошибки. И особенно не за счет целостности данных .
Программа пытается что-то сделать. Если это не удается, вы должны признать факт и сделать что-то с этим. Что это будет, зависит от многих вещей.
В конце пользователь запросил, чтобы программа сделала что-то, и программа должна сказать им, что это не удалось. Есть много способов, как это можно сделать. Он может немедленно остановиться, он может даже откатить уже выполненные шаги или, с другой стороны, он может продолжить и завершить все возможные шаги, а затем сказать пользователю, что эти шаги выполнены успешно, а другие - не пройдены.
Какой способ вы выберете, зависит от того, насколько тесно связаны шаги, и вероятно ли, что ошибка повторится для всех последующих шагов, что, в свою очередь, может зависеть от точной ошибки. Если требуется строгая целостность данных, необходимо выполнить откат до последнего согласованного состояния. Если вы просто копируете кучу файлов, вы можете пропустить некоторые и просто сказать пользователю в конце, что эти файлы не могут быть скопированы. Вы не должны молча пропускать файлы и ничего не говорить пользователю.
Редактирование рекламы, единственное отличие, которое вы вносите, состоит в том, что вам следует подумать о том, чтобы повторить попытку несколько раз, прежде чем бросить и сказать пользователю, что это не сработало, поскольку в сети могут возникать временные ошибки, которые не повторятся при повторной попытке.
источник
Существует один класс случаев, когда игнорирование ошибок является правильным решением: когда ничего нельзя сделать с ситуацией и когда плохие и, возможно, неправильные результаты лучше, чем отсутствие результатов.
Случай декодирования потока HDMI для отображения является таким случаем. Если поток плохой, он плохой, кричать об этом не будет волшебным образом. Вы делаете все возможное, чтобы отобразить это, и позволить зрителю решить, терпимо ли это или нет.
источник
Я не верю, что программа должна молча игнорировать или вызывать хаос, когда сталкивается с проблемой.
Что я делаю с внутренним программным обеспечением, которое я пишу для своей компании ...
Это зависит от ошибки, скажем, если это критическая функция, которая вводит данные в MySQL, она должна сообщить пользователю, что произошла ошибка. Обработчик ошибок должен попытаться собрать как можно больше информации и дать пользователю представление о том, как исправить ошибку самостоятельно, чтобы они могли сохранить данные. Я также хотел бы предоставить способ молча отправить нам информацию, которую они пытались сохранить, чтобы в случае ухудшения ситуации мы могли ввести его вручную после исправления ошибки.
Если это не критическая функция, которая может привести к ошибкам и не повлиять на конечный результат того, чего они пытаются достичь, я могу не показывать им сообщение об ошибке, а отправить его по электронной почте, чтобы автоматически вставить его в нашу программу отслеживания ошибок. или группа рассылки электронной почты, которая предупреждает всех программистов в компании, чтобы мы знали об ошибке, даже если пользователь не знает об этом. Это позволяет нам исправить заднюю часть, пока на передней части никто не знает, что происходит.
Одна из самых больших вещей, которых я стараюсь избегать, - это сбой программы после ошибки - невозможность восстановления. Я всегда стараюсь дать пользователю возможность продолжить, не закрывая приложение.
Я считаю, что если никто не знает об ошибке - она никогда не будет исправлена. Я также твердо верю в обработку ошибок, которая позволяет приложению продолжать функционировать после обнаружения ошибки.
Если ошибка связана с сетью - почему бы не выполнить функции простого теста сетевой связи перед выполнением этой функции, чтобы избежать ошибки в первую очередь? Затем просто предупредите пользователя о том, что соединение не доступно, проверьте ваш интернет и т. Д. И т. Д. И попробуйте еще раз?
источник
Моя собственная стратегия - различать ошибки кодирования (ошибки) и ошибки времени выполнения и, насколько это возможно, затруднять создание ошибок кодирования.
Ошибки должны быть исправлены как можно скорее, поэтому подход « Проектирование по контракту» подходит. В C ++ мне нравится проверять все мои предварительные условия (входные данные) с утверждениями в верхней части функции, чтобы как можно быстрее обнаружить ошибку и упростить присоединение отладчика и исправление ошибки. Если разработчик или тестировщик вместо этого решат продолжить выполнение программы, любая проблема потери целостности данных становится их проблемой.
И найдите способы предотвратить ошибку в первую очередь. Быть строгим с константностью и выбирать типы данных, подходящие для данных, которые они будут хранить, - два способа усложнить создание ошибок. Fail-Fast также хорош вне критического для безопасности кода, который нуждается в способе восстановления.
Для ошибок времени выполнения, которые могут произойти с кодом без ошибок, таким как сбои сети или последовательной связи или отсутствующие или поврежденные файлы:
источник
Сбой - это правильный вариант, когда у вас есть основания полагать, что общее состояние программы нестабильно и что-то плохое может случиться, если вы позволите ей работать с этого момента. В некоторой степени «игнорирование» этого (т. Е. Как указали другие, занесение его в журнал или вывод сообщения об ошибке пользователю, а затем продолжение) - это нормально, если вы знаете, что, конечно, текущая операция не может быть выполнена, но программа может продолжать работать.
источник