Почему исключения считаются настолько плохими для проверки входных данных? - PullRequest
46 голосов
/ 04 января 2009

Я понимаю, что "Исключения для исключительных случаев" [a], но, помимо повторения более и более , я так и не нашел фактическую причину этого факта .

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

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

Ввод не то, что ожидалось, и, следовательно, является исключительным. Создание исключения позволяет мне точно определить, что было неправильно, например StringValueTooLong или IntegerValueTooLow или InvalidDateValue или что-то еще. Почему это считается неправильным?

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

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

a: Везде, где я читал что-либо об Исключениях.

--- Редактировать ---

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

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

Ответы [ 17 ]

31 голосов
/ 04 января 2009

Читая эти ответы, я нахожу очень бесполезным сказать: «Исключения следует использовать только для исключительных условий». Отсюда возникает целый вопрос о том, что является «исключительным условием». Это субъективный термин, лучшее определение которого - «любое условие, с которым ваш нормальный логический поток не справляется». Другими словами, исключительное условие - это любое условие, с которым вы имеете дело, используя исключения.

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

Если вы собираетесь спорить с исключениями в определенном случае, вы должны объяснить, как разделить совокупность условий на «исключительные» и «не исключительные».

В некотором смысле это похоже на ответ на вопрос "где границы между процедурами?" Ответ таков: «Куда бы вы ни положили начало и конец», а затем мы можем поговорить о практических правилах и различных стилях для определения того, куда их поместить. Здесь нет жестких и быстрых правил.

21 голосов
/ 04 января 2009

Пользователь, вводящий «плохой» ввод, не является исключением: его следует ожидать.

Исключения не должны использоваться для нормального потока управления.

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

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

8 голосов
/ 04 января 2009

Существует одна важная другая причина, кроме уже упомянутых:

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

В C # это возможно (и я искренне рекомендую это), особенно после того, как они добавили методы TryParse ко всем классам чисел. В общем, ни одна из стандартных библиотек не требует и не использует «плохую» обработку исключений. Когда я подхожу к кодовой базе C #, которая не была написана в этом стандарте, я всегда заканчиваю тем, что преобразовываю ее в случаи, свободные от исключений для регулярных, потому что stop-om-throw очень ценен.

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

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

6 голосов
/ 10 июля 2014

Ошибки и исключения - что, когда и где?

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

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

Существует три вида ошибок:

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

Любое другое условие не ошибка и не должно сообщаться как ошибка.

Почему исключения считаются настолько плохими для проверки входных данных?

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

5 голосов
/ 04 января 2009

Я думаю, что разница зависит от контракта определенного класса, т.е.

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

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

4 голосов
/ 04 января 2009
  1. Ремонтопригодность - Создание исключений нечетные пути кода, мало чем отличающиеся от GOTO.
  2. Удобство использования (для других классов) - Другие классы могут доверять этому исключения подняты от вашего пользователя входными классами являются действительные ошибки
  3. Производительность - На большинстве языков Исключение влечет за собой исполнение и штраф за использование памяти.
  4. Семантика - Значение слов имеет значение. Плохой ввод не "Исключительный".
3 голосов
/ 04 января 2009

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

Если вы когда-либо когда-либо вызываете исключение, когда выполняете простые логические операции, такие как проверка пользовательского ввода, вы делаете что-то очень, очень, очень неправильное.

Ввод не то, что ожидалось, и следовательно, является исключительным.

Это утверждение не совсем подходит мне. Либо пользовательский интерфейс ограничивает пользовательский ввод (например, использование ползунка, который ограничивает минимальные / максимальные значения), и теперь вы можете утверждать определенные условия - обработка ошибок не требуется. Или пользователь может ввести мусор, и вы ожидаете, что это произойдет, и должны справиться с этим. Одно или другое - здесь нет ничего исключительного.

Создание исключения позволяет мне точно определить, что было не так, как StringValueTooLong или или IntegerValueTooLow или InvalidDateValue или что угодно. Почему это считается неправильно?

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

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

3 голосов
/ 04 января 2009

Возможно ли, что некоторые разногласия связаны с отсутствием единого мнения о том, что означает «пользовательский ввод»? И действительно, на каком слое вы кодируете.

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

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

Если вы кодируете сервер на уровне протокола, вы можете разумно ожидать, что клиент будет проверять пользовательский ввод. Опять же, неверный ввод здесь действительно будет исключением. Это сильно отличается от доверия клиенту на 100% (это было бы очень глупо), но в отличие от прямого пользовательского ввода, вы предсказываете, что большую часть времени ввода будет в порядке. Линии здесь несколько размыты. Чем выше вероятность того, что что-то случится, тем меньше вы захотите использовать исключения для обработки этого.

3 голосов
/ 31 декабря 2010

Это языковая точка зрения (точка зрения) по этому вопросу.

Почему исключения считаются настолько плохими для проверки входных данных?

вывод:

  • Исключения недостаточно четко определены, поэтому существуют разные мнения.
  • Неправильный ввод рассматривается как нормальная вещь, а не как исключение.

мысли?

Вероятно, все сводится к ожиданиям от создаваемого кода.

  • клиенту нельзя доверять
    • проверка должна произойти на стороне сервера. сильнее: каждые проверка происходит на стороне сервера.
    • , поскольку проверка происходит на стороне сервера, ожидается , что ожидается, и то, что ожидается, не является исключением, поскольку ожидается.

Однако

  • ввод клиента нельзя доверять
  • Подтверждение ввода клиента Можно доверять
    • если проверка достоверна, ожидается, что ожидается для получения правильного ввода
    • теперь ожидается, что каждый ввод будет действительным
    • неверный ввод теперь неожиданный, исключение

.

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

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

2 голосов
/ 04 января 2009

Еще один голос против обработки исключений для вещей, которые не являются исключениями!

  1. В .NET JIT-компилятор не будет выполнять оптимизацию в определенных случаях, даже если исключения не генерируются. Следующие статьи объясняют это хорошо. http://msmvps.com/blogs/peterritchie/archive/2007/06/22/performance-implications-of-try-catch-finally.aspx http://msmvps.com/blogs/peterritchie/archive/2007/07/12/performance-implications-of-try-catch-finally-part-two.aspx

  2. Когда генерируется исключение, оно генерирует целую кучу информации для трассировки стека, которая может не понадобиться, если вы действительно «ожидали» исключение, как это часто бывает при преобразовании строк в int и т. Д. ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...