Это хорошая или плохая идея - выдавать исключения при проверке данных? - PullRequest
58 голосов
/ 01 октября 2009

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

Примечание: У меня нет отдельных логических значений для каждого чека. Это только для примера.

Другое примечание: любая обработка ошибок во время тестов выполняется правильно. ЕДИНСТВЕННЫЕ исключения, добавленные в try-catch, - мои собственные.

try {
  if (validCheckOne = false) {
    throw new Exception("Check one is bad");
  }
  if (validCheckTwo = false) {
    throw new Exception("Failed because of check2");
  }
  if(validCheckTen = false) {
    throw new Exception("Yet another failure on your part: check10.");
  }
} catch(Exception e) {
  MessageBox.Show("Your stupid data is wrong! See for yourself: " + e.Message);
}

Это плохая практика? Вызывает ли исключение замедление выполнения программы или нецелесообразно?

Ответы [ 13 ]

58 голосов
/ 01 октября 2009

Лично мне нравится генерировать исключения для проверки бизнес-правил (не так сильно для проверки ввода пользователя), потому что это заставляет проблему обрабатываться вверх по течению. Если мои бизнес-объекты вернули какой-либо результат проверки, он может быть проигнорирован вызывающей стороной. Назовите меня ковбоем, если хотите :) 1001 *

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

31 голосов
/ 01 октября 2009

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

18 голосов
/ 01 октября 2009

Я поддерживаю ответ MusiGenesis.

Дополнительно ...


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

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

12 голосов
/ 01 октября 2009

В дополнение к часто повторяемому утверждению о том, что «исключения являются исключительными обстоятельствами», вот еще одно уточняющее правило, которое мне понравилось:

Если пользователь вызвал это, это не исключение.

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

7 голосов
/ 01 октября 2009

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

Но проверка данных также может происходить на других границах, например, между классами бизнес-правил. Там ошибки в данных редки и неожиданны. Вы должны бросить, когда обнаружите один.

5 голосов
/ 01 октября 2009

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

3 голосов
/ 01 октября 2009

Так что, возможно, в некоторых языках создание и отлов исключений является «дорогостоящим», но в других языках создание и отлов исключений - это именно то, что требуется.

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

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

2 голосов
/ 01 октября 2009

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

  error = false;
  while(true) {
    if(validCheckOne == false) { 
       msg = "Check one is bad"; 
       error = true;
       break;
    }

    if(validCheckTwo == false) { 
       msg = "Check two is bad"; 
       error = true;
       break;
    }
    ...
    break;
  }
  if (error) {
     ..
  }

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

2 голосов
/ 01 октября 2009

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

1 голос
/ 07 сентября 2017

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

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

Другая потенциальная проблема с вашим примером кода (в зависимости от требований, конечно) заключается в том, что он генерирует только первую ошибку проверки. Представьте себе это от пользователя POV:

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

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

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